------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
Collection集合框架 | 特点 | 在java中,由于数据结构的不同,存储方式也不一样,对于结合框架中用来获取元素并且返回值类型为接口型的方法,是因为在不同的数据结构的集合中,java定义了相应的实现Collection的内部类来接收这些数据,并将这些内部类封装起来,对外提供方法来获取这些内部类实例,并将返回值类型固定为接口型的,以便接收被封装的实例(多态的体现) |
集合 | 用于存储对象 | |
List接口,有序,可重复 | ArrayList类,数组结构,有索引查询效率高,增删效率低,线程不同步,默认长度10 | |
LinkedList类,链表结构,数据只记录前后位置,查询效率低,增删数据效率高 | ||
Vector类,数组结构,线程同步,与ArrayList是同步的,已被淘汰,默认长度15 | ||
Set接口,无序,不可重复,功能与父接口一致 | HashSet,底层数据结构为hash表,线程不同步 | |
TreeSet,底层数据结构为二叉树,可以对集合中的元素进行排序 | ||
子类构造方法 | 1、空参 2、(Collection<? extends E> coll)将指定集合转换为该集合 | |
Collection接口 | 概念 | 由Set和List等接口向上抽取得到的接口,包括集合的公共方法 |
增 | 确保包含(添加):boolean add(elements),Collection被改变则返回true,否则false 确保包含A中所有:boolean addAll(Collection A),同上被改变则返回true,否则false | |
删 | 确保移除:boolean remove(elements),成功移除返回true 确保移除A中也有的部分:boolean removeAll(A),发生更改返回true 确保保留A中也有的部分:boolean retain(A),发生更改返回true 确保清空:boolean clear(),成功清空返回true 这些方法底层同样依赖的是equals方法 | |
改 | 无此方法 | |
查 | 查询元素数量:int size() 查询哈希值:int hashCode() | |
判断 | 是否为空:boolean isEmpty() 是否包含:boolean contains(obj)注意此方法底层会调用obj类的equals方法去比较,也就是说,如果obj是String类的,判断是否包含会比较字符串是否相等,而不是对象地址值是否相同,如果obj没有复写Object类的equals方法,则会比较内存地址,如果要自定义contains的标准,必须在obj所属的类中复写equals方法 是否包含A中所有:boolean containsAll(A) 是否与A相同:boolean equals(A) | |
获取迭代器 | 获取与该集合对应的迭代器,用于获取元素:Iterator iterator() | |
转换为数组(作用:限制元素的操作) | <T> T[] toArray(T[n] a) 指定一个T类型数组,当n小于集合size的时候,会自动创建一个补齐长度的新数组,当n超过集合size时,会以默认值填补超过的部分 Object[] toArray() 转换为一个Object类型数组 | |
Iterator接口(迭代器) | 概念 | 集合框架底下由于数据存储的方式不同,获取数据的方式也不相同,java将获取数据这个功能按照获取方式的不同封装为内部类,存储在不同的集合类中,并且根据共性向上抽取为接口Iterator,通过对外提供的方法,如iterator等来返回一个内部类(Itr)的实例,并将返回值类型定为接口Iterator,以便接受被封装的实例(多态的体现)。 |
注意 | 不能在创建迭代器和使用迭代器的中间过程使用集合的方法对集合进行更改(如增删等),否则会发生并发修改异常:ConcurrentModificationException | |
判断 | 判断是否仍有元素可迭代:boolean hasNext(),注意并不会改变集合 | |
获取 | 返回迭代的下一个元素:E next(),注意并不会改变集合 | |
移除 | 从迭代器对应的Collection中移除迭代器返回的最后一个元素:void remove() | |
List接口 | 特点 | 具备索引,因此具备按照索引进行数据操作的特有方式同时具备特有的迭代器ListIterator,注意List集合在判断是否包含以及删除等操作时,依赖的是底层方法时元素所属类的equals方法 |
增 | 指定位置插入: void add(int index, E element),该角标之后元素顺延 指定位置插入所有:boolean addAll(Collection<? extends E> c)改变则返回true | |
删 | 删除指定位置元素: E remove(int index) 注意此方法与其父类的方法很相似,如果存的是Integer类型对象,在删除时不会自动装箱,而是当作角标看待 | |
改 | 将指定位置元素更改为element:E set(int index, E element) | |
查 | 获取指定位置的元素:E get(int index) 获取指定区间的子集: List<E> subList(int fromIndex, int toIndex) 获取ListIterator: ListIterator<E> listIterator()重载带index参数则是获取从指定位置开始的迭代器 获取该元素出现的位置: int indexOf(Object o) 反向获取: int lastIndexOf(Object o) | |
ListIterator | List集合所特有的迭代器,是Iterator的子接口。在使用迭代器方法时,如果同时使用集合的方法对元素进行操作,会发生并发修改异常,而Iterator方法有限,因此通过此子接口的方法对元素进行操作 | |
插入:void add(E e) | ||
反向判断与反向获取: boolean hasPrevious() ,E previous() | ||
获取next元素索引或反向next元素索引:int nextIndex(),int previousIndex() | ||
将当前索引元素更改为element:E set(E element) | ||
Vector类 | 概论 | 此类已濒临淘汰,仅剩枚举 |
方法 | Enumeration elements()获取该向量组件的枚举 | |
Enumeration | 使用方式和迭代器类似 | |
判断是否有更多元素:boolean hasMoreElements() | ||
获取下一个元素:E nextElement() | ||
LinkedList | 获取 | 获取第一个:E getFirst() 获取最后一个:E getLast() |
插入 | 第一个位置插入e:void addFirst(e) 最后位置插入:void addLast(e) | |
删除 | 移除第一个并获取第一个:E removeFirst() 移除最后一个并获取最后一个:E removeLast() | |
注意 | 以上获取和删除方法在列表为null时将抛出NoSuchElementException,因此正被以下新方法淘汰 | |
1.6获取 | 获取第一个:E peekFirst(),列表为空返回null 获取最后一个:E peekLast(),列表为空返回null | |
1.6插入 | 第一个位置插入e:void offerFirst(e) 最后位置插入:void offerLast(e) | |
1.6删除 | 移除第一个并获取第一个:E pollFirst() 移除最后一个并获取最后一个:E pollLast() | |
HashSet | 存储特点 | 相对于List集合,会先判断对象的哈希值,如果不同,则属于不同元素,可以存储; 如果相同,会调用对象所属类的equals方法判断对象是否相同,如果相同,不进行存储,如果不同,则在哈希表中同一哈希值下,将元素串起来,进行存储; 也就说,如果元素所属类没有复写equals方法和hashCode方法,任何两个该类元素都不属于相同元素,这是因为系统会默认分配不同的hash值,更何况equals方法比较的也是hash值 |
保障元素惟一性 | 在存储自定义对象时,如人类,当姓名和年龄均不同时视为不同对象。这时,如果让系统自动分配哈希值,那么属性一样的会存储进去。因此,必须通过复写该类的hashCode方法,通过return一个与对象的属性相关的hash值,来保证姓名年龄属性不同的对象,哈希值也不同(由于复写方式,不是100%不同,但即使相同,在第二步时肯定也不会再相同)。第二步,对于属性相同的元素,通过复写equals方法,来判断出两个对象是否相同。这样就可以保障HashSet不会存储相同元素 | |
复写hashCode方式 | 将方法体改为return 属性相关的HashCode计算值,注意不要超过int范围,如上述的人类在复写hashCode时可写为:return this.name.hashCode()+age*29; 也可以改为一个固定值,但是这样每次都要调用equals方法判断,效率低,不推荐。 | |
总结 | HashSet在判断是否存在和删除等操作时,依赖的也是hashCode和equals两个方法,因此在创建类时,如果这类对象有使用一般情况下,要复写equals和hashCode方法 | |
LinkedHashSet | 链表结构的set集合,HashSet的子类,有序且不重复 | |
TreeSet | 存储特点 | 采用二叉树结构进行存储,小的放左下角,大的放右下角;取出时,从小往大取 TreeSet在存储时元素时,会调用底层compareTo方法对元素进行比较,所以要使用TreeSet对元素进行操作,必须使元素具备可比性或者指定TreeSet所使用的比较器,而想要自定义元素的排序方式以及相同的条件,那么就要自定义比较器或者实现Comparable并复写compareTo方法 |
compareTo方法 | 1、返回值类型为int,大于0表示大于,小于0表示小于,等于0表示元素相同,TreeSet不会进行存储(可使用-1,0,1),主要属性比较完,还需要在为0的条件中对次要属性继续判断,因为一般情况下,只要有一个属性不同,就是不同的对象; 2、想要使TreeSet按照存入的顺序(反向)来保存数据,可将return的值为0以外的条件全部固定为正数或负数 | |
方式1 | 1、让元素所在类实现Comparable接口,使该类对象具备可比性 2、复写接口中的唯一方法:int compareTo(Object obj) | |
方式2 | 1、创建一个类(可以是内部类),该类实现接口Comparator<T>比较器 2、复写比较器中的方法int compare(Object obj1,Object obj2) 3、将比较器实例以参数形式传递给TreeSet的构造方法TreeSet(Comparator<? super E> comparator),注意TreeSet可接受元素父类的比较器 可用匿名内部类的方式来传递参数 | |
注意: | 在两种方式共存的情况下,默认使用方式2,因此即使元素所属类实现了Comparable,如果不想要该排序方式,也不需要去更改这个类,直接另外定义比较器就行了 | |
总结 | TreeSet在判断是否存在和删除等操作时,依赖的是compareTo方法,因此在创建类时,如果这类对象要使用TreeSet,一般情况下要复写该方法或自定义比较器 |