黑马程序员---集合框架知识点总结

---------------------- 黑马程序员 Android培训、期待与您交流! ---------------------

Collection集合类

为什么出现集合类?

    面向对象的语言对于事物的体现都是以对象的形式。为了方便对多个对象进行操作,需要将对象进行存储,方式有二:数组和集合,这两者本质上都是容器。数据多了用对象存。

 

    集合的特点: 

             1. 长度可变。2. 只能储存对象。3. 可以储存不同类型的对象。

  

  集合就是容器,集合本身也是对象,也可以装填对象。集合有很多种,利用共性不断向上抽取,最终形成体系,称为“集合框架”。查阅顶层函数,创建底层对象。先看顶层,对整个体系有个大致的了解。顶层的是Collection接口,意为,集合、容器。

    集合框架属于工具包的成员,在java.util中,顶层的Collection是一个接口。

     

    Collection(接口)

    add(Object obj):1. 参数类型是Object,可以接受任意类型对象;2. 集合中存放的都是对象的地址值(引用)。add语句的返回值是布尔型,表示是否已经存入

    可以直接打印集合,所有元素放在中括号中。

    remove(Object obj);删除指定元素。返回布尔型值,表示是否已经删除。底层调用equals方法,确定删除哪个元素。

    clear();清空集合。

    retain(Collection e);集合之间取交集。例如,arr1.retainAll(arr2);,arr1中只会保留和arr2相同的元素。没有交集,显示为空。

    removeAll();去掉相同元素保留不同元素。例如,arr1.removeAll(arr2);

    contains();是否包含某元素。通过判断对象是否相同确定是否包含,实质是底层自动调用equals方法。通过复写equals方法来满足其他需求,例如比较对象的属性。

    获取元素的目的是操作元素,不一定打印。

 

    Iterator接口

    Iterator是一个接口,可以建立引用,指向子类的对象;这个对象不是通过new建立的,而是通过iterator方法建立的,例如,Iterator it = arr1.iterator();。获取迭代器,用于取出集合中的元素。

 

1. 每个集合都需要取出数据进行操作,所以将取出动作定义在集合的内部,使得取出动作可以直接访问集合内部的元素。

2. 因为取出动作无法用一个功能就能描述,需要多个功能配合使用才行,例如,判断和取出。集合就将取出动作封装成对象,通过内部类(私有,隐式,Itr类)对取出动作进行描述。(这就是“内部类的设计”)通过iterator()方法创建对象,每个集合的iterator()内容都不一样。

也就是说,定义一个内部类,对集合的内部数据进行操作。每个集合都有内部类,以后再创建集合也需要内部类。

3.因为不同集合数据结构不同,所以取出动作细节不同。但都有共同的内容,就是所有的内部类都有判断和取出这2个功能。可以将这2个功能抽象出来,形成一个接口,或者说规则,即Iterretor,内部有判断和取出的函数声明但没有实质内容。这样就统一了取出方式,以后有集合,只需要实现Iterator接口即可。

 

迭代器出现的原因

1.集合都有操作数据的需求。2. 取出数据的动作无法用一个函数描述,需要将取出封装成对象并通过内部类描述。3. 因为集合的数据结构不同,具体实现细节也不同,导致每个集合都有自己的取出对象和内部类。

如何获取集合的取出对象?每个集合都通过对外提供的一个方法,iteretor()。接口提供引用,集合提供对象,配合在一起使用,降低了使用者和取出动作的耦合性。2种方法:

Iterator it = arr1.iterator();//阅读性比较好。

while(it.hasNext())

{

       sop(it.next());//注意:it.next()返回的是Object类指向。

}

-------------------------------------------

for(Iterator it = arr1.iterator();it.hasNext(); )//将it作为局部变量,节省了资源。

{

       sop(it.next());

}

 

Collection(所有子类共享的方法add、remove、contains、clear、iterators)

       List(类)元素是有序的,并且可以重复,因为该集合体系有索引。

       ArrayList(类):底层的数据结构是数组结构。特点:查询速度块,但是增删稍慢。线程不同步。通过加锁可以用于多线程。可变长度数据,默认长度为10,超过10后,创建50%延长的新数据(节省空间),并将数据存到新数组中,依次执行。

       LinkedList:底层使用链表数据结构,通过关联将数据连接在一起,每个数据只知道自己前面的数据。查询比较麻烦,但是增删很方便。

       Vector:底层是数据数据结构,和ArrayList功能一样。元老,早于Collection存在。线程同步的,极少使用,被ArrayList替代了。100%延长数组。

       Set(接口)元素是无序的(存入和取出的顺序不一定一致),不可以重复,因为没有索引。功能和Collection几乎是一致的。

       HashSet底层数据结构是哈希表。

      TreeSet底层是二叉树结构。

 

List集合

特有方法:凡是可以操作角标的方法都是该体系特有的方法。

判断元素是否相同,依据的是元素的equals方法。其他集合不同。

添加:

add(int index, Object element);只能有序添加,不能越位添加元素,否则异常。插入元素,后面的元素向后顺延。

add(int index, Collection)

 

删除:

remove(int index)

 

修改:

set(int index, Object element)

 

查找:

get(int index)

List subList(int from, int to);注意返回值类型为List,可以直接打印。

    listIterator();列表迭代器,

    indexOf(Object obj);

   

    并发访问:不能对同一组元素做多种同时操作,会有安全隐患。例如,

Object obj = it.next();//迭代操作

if(obj.equals("java02"))

              arr.add("C++");//迭代器不知道又添加了新元素。

    安全的做法是,要么全用集合方法,要么全用迭代器方法,不能迭代中用集合

    Object obj = it.next();

       if(obj.equals("java02"))

       it.remove();

       sop("obj="+obj);//集合中元素已经消失,但其指向仍然被Object使用,所以仍然可以打印”java02”。

 

    List集合特有迭代器ListIterater是Iterator的子类接口。

    在迭代时,不可以通过集合对象的方法操作集合中的元素,会发生并发异常。所以在迭代时,只能用迭代器的方法操作元素,Iterator的方法是有限的,只有判断、取出和删除的操作,适合遍历使用;如果想要其他的操作,就需要使用ListIterator接口。该接口只能通过List集合的 listIterator方法获取。例如,ListIterator it = arr.listIterator();和上面一样,遍历时的添加不能打印。

    迭代器中的指针有记录功能,会记住所在位置。所以循环中,hasNext()判断一次,next()就执行一次,最为安全。

hasPrevious();指针前面是否有元素;hasNext();指针下面是否有元素。对应的获取元素方法:next();获取下一个元素(正向遍历);previous();获取上一个元素(逆向遍历)。

   

    Vector集合与枚举

    枚举:element()方法和Enumeration接口。早期,枚举是Vector特有的取出方式。其实枚举和迭代器是一样的。因为枚举的名称和方法的名称都过长,逐渐被迭代器取代了。

    Vector集合取出元素的方式:1. 枚举。2. 迭代器。3. 遍历,for循环。4. 按角标索引,get方法。

    LinkedList集合

    特有方法:

    addFirst();向后挤压,将先前的元素挤到后面。

    addLast();向前挤压。

    获取元素但不删除元素。如果元素被删除,会出现NoSuchElementException异常。

    getFirst();

    getLast();

    获取元素但元素被删除。如果元素被删除,会出现NoSuchElementException异常。

    removeFirst();

    removeLast();

    通过remove方法取出元素,不需要迭代器,例如,

    while(!link.isEmpty())

       {

              sop(link.removeFirst());

       }

LinkedList集合,JDK1.6后出现:

    offerFirst();

    offerLast();

    获取元素但不删除元素。如果元素被删除,返回null。

    peekFirst();

    peekLast();

    获取元素但元素被删除。如果元素被删除,返回null。

pollFirst();

    pollLast();

  

     数据结构不同,某些方法依赖的底层方法也不同,ArrayList和LinkedList中的contains、remove依靠的都是底层的equals。默认的equals方法依据对象的内存地址值来比较对象是否相同,可以根据对象的属性自建equals方法,例如,

    public boolean equals(Object obj)//复写Object中的方法。

       {

              if(!(obj instanceof Person))//是否属于该类的对象,应该抛异常。

                     return false;

              Person p =(Person) obj;

              //System.out.println(this.name+"..."+p.name);//此句打印表示该函数被调用。

              return (this.name.equals(p.name) && this.age==p.age);

       }

    确定使用哪种集合?元素多,频繁使用增删操作,用LinkedList;增删操作比较少的话,两者都可以;查询比较多,用ArrayList,开发中更倾向于ArrayList。

   

    Set集合

    HashSet集合

    哈希表是按照哈希值来存储对象的表,通过哈希值来辨别对象。该表有自己的顺序,与存入顺序不一致。

    通过toString方法和hashCode方法(返回对象哈希值)将对象的哈希值输出,也可以复写方法,自定义哈希值。默认的哈希值是内存地址值,可以根据对象的特点自建hashCode方法,如同自建equals方法。

HashSet如何保证元素的唯一性通过hashCode和equals来完成:先是哈希值,如果不同的话直接存入元素,不调用equals;哈希值相同,再判断equals是否为true。可以复写HashCode方法,自定义哈希值方法,例如,

public int hashCode()

{

     System.out.println(this.name+"..code.."+this.age);

     return this.name.hashCode()+this.age*39;//避免哈希值一致。

}

获得对象独特的哈希值,避免equals判断,提高效率。创建对象都要复写hashCode和equals方法,因为对象有可能会存入HashSet集合中,底层自动调用。

    只能通过迭代器取出元素。取出的元素无序排列。通过输出语句可以判断是否进入哈希表,例如,sop(hs.add("java01"));。

    Set集合中,contains、remove等操作都需要在底层调用hashCode和equals。如果操作没有的元素,只调用hashCode方法,所以真正依赖的是equals方法。原则在于数据结构。与List不同。

---------------------- 黑马程序员 Android培训、期待与您交流! ---------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值