疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java基础系列--集合类库


 

 
1、概述
 
  Java的集合类库很是丰富,囊括了大部分的常见数据结构形式,让我们可以有目的性的选择适合当前业务场景和功能场景的集合类。合适的集合框架可以最大程度的提升执行速度和效率。
 
  Java集合类库中所有的集合类都始于Collection接口和Map接口,前者表示单值集合,后者表示映射集合(双值集合)。
 
  Java集合框架中的Abstract开头的抽象类,其实是JDK开发者定义出来用于实现具体集合类的,是面向JDK开发人员的,而不是面向JDK的使用人员。在这些抽象类中一般会将同一类型的集合的一些公共的方法进行实现,避免在具体的集合类中重复的实现,比如contains方法。
 
2、接口体系
 
 
 
  这个结构系统中,我只是简单的列出了终止于具体集合类型接口的接口继承结构,从中可以明显的看出各个接口的位置,下面让我们来重点介绍一些这些接口,它们的位置及意义。
 
2.1 Iterable接口
 
  这是一个简单的接口,实现了该接口的类都可以使用foreach循环迭代,其实foreach底层原理还是Iterator迭代器循环。从上面的接口可以看出,只有单值集合可以使用这种迭代方式。
 
  它内部只拥有一个方法:
 
1 Iterator<T> iterator();
  这个方法用于返回一个基于类型为T的元素集合的迭代器Iterator。
 
2,2 Iterator接口
 
  这个接口就是迭代器接口,迭代器接口定义了迭代器常用的方法:
 
1     boolean hasNext();
2     E next();
3     void remove();
  这三个方法的意义各不相同,但是在使用上却是互各依赖。
 
  第一个方法hasNext()方法用于验证迭代器中是否还有元素,如果还有元素则返回true,否则返回false
 
  第二个方法next()方法用于获取迭代器的下一个元素,如果当前已经到达迭代器末尾,再次调用该方法就会抛出一个NoSuchElementException异常,因此我们可将此方法与之前的hasNext()方法结合使用,先判断是否拥有下一个元素,然后再获取元素,这样如果不存在下一个元素,就不再获取。
 
  我们可以将next()方法想象成为一个指针,这个指针并不会指向具体的元素,而是指向元素与元素之间的间隙,初始时,该指针位于第一个元素之前的位置,调用next()一次,指针越过第一个元素,指向第一个元素与第二个元素的间隙,而该方法会将越过的元素返回。
 
  第三个方法是remove()方法,用于移除集合中的刚刚被迭代器返回的元素,这个方法的使用是在第二个方法的基础上进行的,即需要先执行next()方法,然后再执行remove()方法,而且两个remove方法不能同时执行(即使是第一个元素的移除也要先执行next将第一个元素返回之后才能执行删除)
 
2.3 ListIterator接口
 
  ListIterator是Iterator的子接口,在原来的基础上专门针对序列进行了扩展,其中定义了如下方法:
 
1     boolean hasNext();
2     E next();
3     boolean hasPrevious();
4     E previous();
5     int nextIndex();
6     int previousIndex();
7     void remove();
8     void set(E e);
9     void add(E e);
  第一个方法:同Iterator
 
  第二个方法:同Iterator
 
  第三个方法:hasPrevious()用于反向遍历时查询是否还有剩余元素,作用同第一个方法,只是方向相反
 
  第四个方法:previous()用于获取反向查询时的下一个元素,越过下一元素并将该元素返回,作用同第二个方法,方向相反
 
  第五个方法:nextIndex()用于返回下一个位置,如果已到末尾,返回list的长度
 
  第六个方法:previousIndex()用于返回前一个位置,如果处于开始位置,返回-1
 
  第七个方法:remove(),同Iterator
 
  第八个方法:set(E e)用于替换最新返回的元素(可能是next方法返回的也可能是previous方法返回的)
 
  第九个方法:add(E e)用于插入新元素到当前序列的next或者previous将会返回的元素的前方/后方
 
2.4 Collection接口
 
  Collection接口是单值集合的根接口,其中为这一类型的集合提供了基本的方法定义:
 
1     int size();
2     boolean isEmpty();
3     boolean contains(Object o);
4     Iterator<E> iterator();
5     Object[] toArray();
6     <T> T[] toArray(T[] a);
7     boolean add(E e);
8     boolean remove(Object o);
9     boolean containsAll(Collection<?> c);
10     boolean addAll(Collection<? extends E> c);   
11     boolean removeAll(Collection<?> c);
12     boolean retainAll(Collection<?> c);
13     void clear();
14     boolean equals(Object o);
15     int hashCode();
  这里列出了Collection接口中定义的所有方法,共有15个:
 
    第一个方法:size()方法用于返回当前集合中元素的数量
 
    第二个方法:isEmpty()用于验证集合中是否包含元素,若包含元素则返回false,若不包含元素则返回true
 
    第三种方法:contains(Object o)验证集合中是否包含指定的元素,若包含则返回true,否则返回false
 
    第四个方法:iterator()用于返回基于当前集合的迭代器Iterator
 
    第五个方法:toArray()用于获取包含当前集合中所有元素的数组,如果集合指定的顺序,那么数组的元素将按照这种顺序排列,并且这个数组将不再与集合有任何的联系,任何针对数组的修改都不会影响到集合。
 
    第六个方法:toArray(T[] a)用于获取包含当前集合中所有元素的数组,与上面的方法不同之处在于,此方法给定一个数组用于存放集合中的元素,若数组足够大能放得下所有的集合元素,则将数组剩余的位置置null,若数组位数不足以保存所有的集合元素,则重新创建一个数组(这个数组与给定的数组的类型一致)来存放集合元素,第二种情况与上面的第五个方法情况相同。由于此方法给定了一个数组用来存放集合元素,因此效率比上面的略高。
 
    第七个方法:add(E e)用于在集合中添加新的元素,如果集合不允许重复元素且已存在该元素,则返回false,如果集合结构发生了变化则返回true(表示添加到集合中了)
 
    第八个方法:remove(Object o)用于移除集合中的某个元素,集合中删除元素会带来集合结构的部分变动。如果集合中包含该元素则返回true
 
    第九个方法:containsAll(Collection<?> c)验证当前集合中是否包含给定集合中的所有元素,如果包含则返回true,否则返回false
 
    第十个方法:addAll(Collection<? extends E> c)用于将指定集合中的所有元素全部添加到当前集合中去,如果指定集合在添加过程中发生的变化则结果将变得不确定。
 
    第十一个方法:removeAll(Collection<?> c)用于移除当前集合中包含的指定集合中的所有元素,如果当前集合发生的改变则返回true
 
    第十二个方法:retainAll(Collection<?> c)用于保留当前集合中同样在指定集合中存在的元素,移除所有不包含在指定集合中的元素,若集合发生的变化则返回true
 
    第十三个方法:clear()用于移除当前集合中的所有元素,之后元素为empty
 
    第十四个方法:equals(Object o)用于比较两个集合对象是否相同
 
    第十五个方法:hashCode()用于返回当前集合对象的hash值
 
2.5 List接口
 
  List是一种有序集,又称序列。拥有下标,允许重复的值。其中定义了序列的一些专有的操作方法:
 
1     E get(int index);
2     E set(int index, E element);
3     void add(int index, E element);
4     E remove(int index);
5     int indexOf(Object o);
6     int lastIndexOf(Object o);
7     ListIterator<E> listIterator();
8     ListIterator<E> listIterator(int index);
9     List<E> subList(int fromIndex, int toIndex);
  第一个方法:get(int index)用于获取执行下标的元素
 
  第二个方法:set(int index,E element)用于设置执行下标的元素,替换指定位置的元素为给定的元素
 
  第三个方法:add(int index, E element)用于在指定位置插入新元素,其后的元素全部后移一位
 
  第四个方法:remove(int index)移除指定位置的元素,其后的元素全部前移一位
 
  第五个方法:indexOf(Object o)获取指定元素在序列中的位置(这里指的是第一次出现的位置),如果不存在则返回-1
 
  第六个方法:lastIndexOf(Object o)获取置顶元素在序列中的位置,方向为从末尾开始(反向)(第一次出现的位置),若不存在返回-1
 
  第七个方法:listIterator()获取一个基于序列中元素的序列迭代器
 
  第八个方法:listIterator(int index)获取一个基于序列中元素的序列迭代器,起始位置为指定的位置
 
  第九个方法:subList(int fromIndex, int toIndex)获取一个子序列,该子序列为截取自当前序列的指定开始位置到指定结束位置的序列段,如果开始位置=结束位置,则该子序列为empty
 
2.6 Set接口
 
  查看源码可知Set接口与Collection接口中定义的方法完全一致,Set集合表示的是无序的集合,其中不能有重复的元素。
 
2.7 Queue接口
 
  Queue是队列接口,用于保存即将进行处理的元素,除了基本的Collection定义的方法之外,队列还提供了其他的插入、提取和移除操作。每个方法都存在两种形式:一种抛出异常(操作出错时),一种返回一个特殊值(null或者false),后面的这种操作是专门为拥有容量限制的Queue为设计的。
 
1     boolean add(E e);
2     boolean offer(E e);
3     E remove();
4     E poll();
5     E element();
6     E peek();
  第一个方法:add(E e)用于插入指定元素到队列中,如果不存在容量限制的情况下。如果执行成功返回true,如果执行失败抛出IllegalStateException异常
 
  第二个方法:offer(E e)用于插入指定元素到队列中,如果不存在容量限制的情况下。当使用的是容量受限的队列,使用该方法将优于add方法。如果执行成功返回true,否则返回false。
 
  第三个方法:remove()用于移出队列顶部的元素,并将移除的元素返回,如果队列是空的,则会抛出一个NoSuchElementException异常
 
  第四个方法:poll()用于移除队列顶部的元素,并将移除的元素返回,如果队列是空的,则会返回null
 
  第五个方法:element(),获取队列顶部的元素(并不移除)如果队列为空,则抛出NoSuchElementException异常
 
  第六个方法:peek()获取队列顶部的元素(并不移除)如果队列为空,则返回null
 
  上面的方法来两两对应,分别用于应对两种不同的情况。
 
2.8 Map接口
 
  Map是一种键值对集合,用于一对一的键值存储,键不能重复,值可以重复,一个键最多只能找到一个值。
 
  Map拥有三种集合视图:键集合(Set),值集合(Collection)、键值映射集合(Set)。
 
  Map集合的顺序被定义为其值集(Collection)的迭代器返回的顺序。
 
  Map集合的键一般使用不可变值,但是值可以使用易变值。因为可变的key可能会影响equals比较。
 
  所有的Map集合的实现类都应该提供两个构造器:一个是无参构造器用于创建一个空的Map集合,一个是带Map集合参数的构造器,用于创建一个与给定集合一一对应的新的Map集合。
 
  Map集合中定义的方法如下:
 
1     int size();   
2     boolean isEmpty();
3     boolean containsKey(Object key);
4     boolean containsValue(Object value);
5     V get(Object key);
6     V put(K key, V value);
7     V remove(Object key);
8     void putAll(Map<? extends K, ? extends V> m);
9     void clear();
10     Set<K> keySet();
11     Collection<V> values();
12     Set<Map.Entry<K, V>> entrySet();
13     boolean equals(Object o);
14     int hashCode();
  第一个方法:size()用于返回Map集合中键值映射的数量
 
  第二个方法:isEmpty()用于验证集合中是否包含键值映射,如果没有表示集合是空的,返回true,否则返回false,表示集合非空
 
  第三个方法:containsKey(Object key)用于验证集合中是否包含指定的键的映射,如果包含返回true,否则返回false(验证集合中是否存在与指定的key相同的键的映射,如果指定的key是null,则查找null为键的映射,否则查找与指定的key一致的键的映射)
 
  第四个方法:containsValue(Object value)用于验证集合中是否存在指定的值的映射(只可以重复,所以此处为至少存在一个),如果至少存在一个则返回true,不存在返回false
 
  第五个方法:get(Object key)用于获取集合映射中指定键的值,如果指定的键不存在则返回null,否则返回对应的值。如果这个集合允许null值,那么返回null值就不确定是不存在映射还是存在映射,只是值为null的情况了,这时可以使用第三个方法来进行区分(通过containsKey(Object key)方法来验证指定的键是否存在,如果存在则返回的是正常保存的null值,否则返回的就是指不存在映射)
 
  第六个方法:put(K key, V value)用于将指定的映射保存到集合中去,如果指定的键已存在(键的存在性判断是通过containsKey(Object key)方法来判断的),则执行的是对应值的替换操作。
 
  第七个方法:remove(Object key)用于移除集合中指定键的映射,并将移除的映射的值返回,如果不存在指定键的映射,则返回null,这对于允许null值的集合来说,又一次产生了歧义,解决方法同上。
 
  第八个方法:putAll(Map<? extends K, ? extends V> m)将指定的map集合中的所有映射拷贝到当前的map集合中去。
 
  第九个方法:clear()用于清空当前的map集合中的所有映射、
 
  第十个方法:keySet()返回map集合中的所有键的集合,这是一个set集合,这个集合就是map集合中键的映射,因此改变其中任何一项都可以在另一个里面发现这种改变。
 
  第十一个方法:values()用于获取map集合中包含的映射中的所有值的集合,这个集合是map集合中值的映射,因此改变其中任何一项都可以在另一个里面发现这种改变。
 
  第十二个方法:entrySet()用于获取map集合中包含的所有映射的集合,这是一个set集合,这个集合就是map集合中映射的映射,因此改变其中任何一项都可以在另一个里面发现这种改变。
 
2.9 Entry<K,V> 内部接口
 
  该接口是在Map接口内部定义的,专门服务于Map集合,用于表示Map集合中的映射,映射表示的是键值对。
 
1         K getKey();
2         V getValue();
3         V setValue(V value);
4         boolean equals(Object o);
5         int hashCode();
  第一种方法:getKey()方法用于获取键值映射中的键
 
  第二种方法:getvalue()方法用于获取键值映射中的值。
 
  第三种方法:setValue(V value)方法用于重置当前键值映射中的值
 
3、总结
 
  上面的所有接口只是简单的对集合类型做了区分,划分了四类集合,分别为Queue队列,List序列,Set集,Map映射集。并对每个类型的集合进行了简单的方法定义,用于确立此类集合的特点。Java中针对每种集合都有多种实现用于应对不同的场景。