集合(2)TreeSet , 泛型

来源:互联网 发布:淘宝美工的前景 编辑:程序博客网 时间:2024/09/21 06:34


TreeSet:  二叉树数据结构,可以对元素进行排序,不同步的。
  如何保证元素唯一性?
  参考的就是比较方法的返回值是否是0,是,就是重复元素,不存。
 **排序方式:需要元素具备比较功能,所以元素需要实现Comparable接口。
              覆盖compareTo方法。
**需求中也有这样一种情况,元素具备的比较功能不是所需要的,也就是说不想按照
  自然排序的方法,而是按照自定义的排序方法,对元素就行排序。
而且,存储到TreeSet中的元素万一没有比较功能,该如何排序呢?
 这时,就只能用第二种比较方式--让集合具备比较功能。

初始化TreeSet集合时明确一个比较器。

实现Comparator接口,覆盖compare方法 。将Comparator接口的对象
         作为参数传递给TreeSet集合的构造器。

比较器更为灵活,自然排序通常作为元素的默认排序。


异常: java.lang.ClassCastException
 原因:因为学生要排序,就需要比较,而没有定义比较方法
比较add方法中使用的是Comparable接口的比较方法.

public int compareTo(Object o) //自然排序以年龄升序排序为主,相同则比较姓名
{
 /* Student stu =(Student)0;
   if(this.age>stu.age)
      return 1;
  if(this.age<stu<age)
           return -1;
   return 0;  */

 int temp=this.age=stu.age;
 return temp==0?this.name.compareTo(stu.name):temp;
}

******list ,Set 集合 名称阅读技巧***********
jdk1.2以后出现的集合框架中常用的子类对象,存在规律
   前缀名是数据结构名,后缀名是所属体系名。

ArrayList:数组结构。看到数组,就知道查询快,看到List,就知道可以重复。可以增删改查。
LinkedList: 链表结构,增删快。xxxFirst  xxxLast
HashSet:哈希表,就要想到元素必须覆盖hashCode equals,不保证有序。看到Set,就知道不可以重复
LinkedHashSet:链表+哈希表。可以实现有序,因为有链表。
TreeSet:二叉树,可以排序。就想要两种比较方式:一种是自然排序Comparable,一种是比较器Comparator



*************Foreach语句*******
 JDK1.5特性:
 增强for循环。作用:用于遍历collection集合or 数组
格式:
  for(元素类型变量:Collection容器or数组)

for(Objecct obj: coll)
{
  syso(obj);
 }
对于数组的遍历,如果不操作其角标,可以使用增强for,如果要操作角标,使用传统for

高级for中不能对数据进行操作,会报并发异常。

***传统for循环和增强for循环有什么区别呢?
 增强for必须有被遍历的目标,该目标只能是Collection or 数组


*****Enumeration接口*************
Enumeration:枚举。
  具备枚举取出方式的容器只有Vector。

Vector v =new Vector();
//获取枚举
for(Enumeration en =v.elements();en.hashMoreElements();){
 system.out.print(en.nextElement());
}

***************泛型*********************
 泛型:
     在jdk1.4版本之前,容器什么类型的对象都可以存储。但是在取出时。需要用到对象的特有内容时,需要做向下转型。
  但是对象的类型不一致,导致了向下转型发生了ClassCastException 异常。
 为了避免这个问题,只能主观上控制,往集合中存储的对象保持一致。

jdk1.5以后解决了该问题,在定义集合时,就直接明确集合中存储元素的具体类型。
     这样,编译器在编译时,就可以对集合中存储的对象类型进行检查。
一旦发现类型不匹配,就编译失败。这个技术就是泛型技术。

好处:
    1,将运行时期的问题转移到了编译时期,可以更好的让程序员发现问题并解决问题。
   2,避免了向下转型的麻烦

总结:泛型就是应用在编译时期的一项安全机制。


泛型的擦除:编译器通过泛型对元素类型进行检查,只要检查通过,就会生成class文件,
         但在class文件中,就将泛型标识去掉了。
      

静态方法是无法访问类上定义的泛型的。如果静态方法需要定义泛型,泛型只能定义在方法上。

泛型的表现:
       泛型技术在集合框架中应用的范围很大。
    什么时候需要填写泛型呢? 1,只要看到类,或者接口在描述时 右边定义<>,就需要泛型。
 其实是,容器在不明确操作元素的类型的情况下,对外提供了一个参数<>。
 使用容器时,只要将具体的类型实参传递给该参数即可。
说白了,泛型就是,传递类型参数。


****当要操作的类型不确定的时候,为了扩展,
 可以使用Object 类型来完成。
但是这种方式一些小弊端,会出现转型,向下转型容易在运行时期发生ClassCastException。

jdk1.5以后,新的解决方案。
类型不确定时,可以对外提供参数。有使用通过传递参数的形式完成类型的确定。

泛型类: 在类定义时就明确参数。有使用该类的调用者,来传递具体的类型。


通配符:在不明确具体类型的情况下,可以使用通配符来表示。  <?>

泛型的限定:
 ? extands E : 接收E类型或者E的子类型 // 上限
 ? super E : 接收E类型或者E的父类型   // 下限

什么时候会用到上限呢?
 **一般往集合存储元素时。如果集合定义了E类型通常情况下应该存储E类型的对象
对E的子类型的对象E类型也可以接受,所有这时可以将泛型从E改成 ? extends E .

什么时候用到下限呢?
  当从容器中取出元素操作时,可以用E类型接收,也可以用E的父类型接收。 ? super E


0 0