java基础——2——集合概述

Java的集合类主要由两个接口派生而来:Collection和Map。Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。这里写图片描述

这里写图片描述
Set集合
Set集合是Collection集合的子类,与Collection基本上完全一样,它没有提供额外的方法,只是在行为上略有不同。
Set集合不允许包含相同的元素,如果把两个相同的元素加入到同一个Set集合中去,则添加操作失败,add方法返回false,且新元素不会被加入。
Set判断两个对象相同不是使用==运算符,而是使用equals方法。也就是说,只要两个对象equals方法比较返回true,Set就不会接受这两个对象;反之,则可以。
HashSet类
HashSet是Set接口的典型实现,大多数时候使用Set集合时就是使用这个实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。
HashSet具有以下特点:
不能保证元素的排列顺序,排列顺序可能与添加顺序不同。
HashSet不是同步的,如果多个线程同时访问一个HashSet时,假设有一个或多个线程同时修改了HashSet集合时,则必须通过代码块来保证其同步。
集合元素可以是null。
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的值,然后根据该HashCode()值决定该对象在HashSet中的存储位置。如果两个元素通过equals()方法比较返回true,而他们的hashCode()方法返回值不同,HashSet会将他们存储在不同的位置,依然添加成功。这就与Set集合的规则有些出入了。
注意:如果通过equals方法比较返回true,同时根据hashCode()方法获取的返回值也相同,则只能存储一个对象。
当把一个对象放入到HashSet中时,如果重写了这个对象的equals方法,那么也必须重写这个对象的hashCode方法。其规则就是如果equals方法返回true,那么这两个对象的hashCode的值也应该相同。
如果两个对象通过equals方法比较返回false,而hashCode值返回一样,这就有点违背了HashSet的设计规则,本来通过Hash算法我们可以计算对象的存储位置,现在却成了在同一个位置上存储了两个对象。从而减低了HashSet快速查找对象的功能。
LinkedHashSet类
LinkedHashSet是HashSet的子类,LinkedHashSet同样是根据元素的hashCode值来决定元素的存储位置,但与HashSet不同的是,LinkedHashSet在存储对象时同时使用链表维护了元素的次序,即:当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按照元素的添加顺序来访问集合里的元素。
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。与HashSet相比,TreeSet还提供了额外方法:
Comparator comparator():如果TreeSet采用了定制排序,则该方法返回定制排序所使用的Comparator,如果TreeSet采用了自然排序,则返回null。
Object first():返回集合中的第一个元素。
Object last():返回集合中的最后一个元素。
Object lower(Object obj):返回集合中位于指定元素之前的元素。
Object higher(Object obj):返回集合中位于指定元素之后的元素。
SortedSet subSet(fromElement,toElement):返回此Set的子集合,范围从fromElement(包含)到toElement(不包含)。
SortedSet headSet(toElement):返回Set的子集,由小于toElement的元素组成。
SortedSet tailSet(fromElement):返回Set的子集,由大于或等于fromElement的元素组成。
HashSet集合采用hash算法来决定元素的存储位置,TreeSet采用红黑树的数据结构来存储集合元素。TreeSet支持两种排序方法:自然排序和定制排序。
自然排序
TreeSet会调用集合元素的compareTo(Object obj):方法来比较元素之间的大小关系,然后将集合元素按升序排列,这种方式就是自然排序。
Java中提供了一个Comparable接口,此接口中定义了一个方法compareTo(Object obj),该方法返回一个整数值,实现了该接口的类的对象就可以比较大小。由于在向TreeSet集合中存放数据时,TreeSet会调用该元素对象的compareTo方法,因此往TreeSet集合中存放是元素对象必须实现了该方法。
大部分类在实现compareTo方法时,都需要将被比较对象obj强制转换成相同类型,因为只有相同类型的实例才能比较大小。因此TreeSet集合中存放的元素必须是同一类型的实例。
否则将会抛出ClassCastException(强制类型转换异常)
定制排序
TreeSet的自然排序是根据集合元素的大小,TreeSet将它们以升序排序。如果实现定制排序,比如降序,需要通过Comparator接口来实现。在创建TreeSet实例的时候,不在使用TreeSet默认的比较,通过Comparator接口实现自己的比较器实例,将比较器的实例作为参数通过TreeSet的构造器传递给集合,那么在往集合元素中存放数据的时候就会按照我们的指定顺序进行排序。实现Comparator接口的int compare(T t1,T t2)方法,此方法在往集合元素中添加元素对象时被调用,该方法返回一个int类型值,返回正整数,表示t1大于t2,返回负整数,表示t1小于t2,返回0表示,t1等于t2.
List集合
List集合代表一个存放元素对象为有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引。
List作为Collection接口的子接口,可以使用Collection接口里的全部方法。由于List又是一个有序的集合,所以List集合中又增加了一些根据索引来操作集合元素的方法。
void add(int index,Object element):将元素element插入到List集合的index处。如果当前索引位置有元素对象,则将此元素对象及后面所有元素对象都向后移动一个索引位置。
Boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入到List集合中的index索引位置。
Object get(int index):返回集合index索引位置的元素。
Int indexOf(Object o):返回对象o在List集合中第一次出现的位置索引。
Int lastIndexOf(Object o):返回对象o在List集合中最后一次出现的位置索引。
Object remove(int index):删除index索引位置的元素,并将此对象返回。同时此元素后面的所有元素索引向前前进一位。
Object set(int index,Object element):将index索引处的元素替换成element对象,并将被替换的元素返回。
List subList(int fromIndex,int toIndex):返回从元素索引fromIndex到索引toIndex处所有集合元素组成的子集合。
List作为Collection接口的子接口,可以使用Collection接口里的全部方法。由于List又是一个有序的集合,所以List集合中又增加了一些根据索引来操作集合元素的方法。
void add(int index,Object element):将元素element插入到List集合的index处。如果当前索引位置有元素对象,则将此元素对象及后面所有元素对象都向后移动一个索引位置。
Boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入到List集合中的index索引位置。
Object get(int index):返回集合index索引位置的元素。
Int indexOf(Object o):返回对象o在List集合中第一次出现的位置索引。
Int lastIndexOf(Object o):返回对象o在List集合中最后一次出现的位置索引。
Object remove(int index):删除index索引位置的元素,并将此对象返回。同时此元素后面的所有元素索引向前前进一位。
Object set(int index,Object element):将index索引处的元素替换成element对象,并将被替换的元素返回。
List subList(int fromIndex,int toIndex):返回从元素索引fromIndex到索引toIndex处所有集合元素组成的子集合。
ListIterator接口:List提供了一个listIterator()方法,该方法返回一个ListIterator对象,ListIterator接口继承了Iterator接口,还提供了专门操作List的方法。方法如下:
Boolean hasPrevious():返回该迭代器关联的集合是否含有上一个元素。
Object previous():返回迭代器的上一个元素。
void add():在指定位置插入一个元素。
ListIterator与普通的Iterator进行对比,ListIterator增加向前迭代的功能,而且还通过add方法向List集合中添加元素。
ArrayList和Vector是List接口的典型实现,都是基于数组实现的List类。ArrayList和Vector都封装了一个动态的允许再分配的Object[]数组。
ArrayList和Vector的用法几乎完全一样,但是Vector与ArrayList相比较而言是属于古董级别,在JDK1.0时就已经存在。那时Java还没有提供系统的集合框架,Vector中提供了很多方法名很长的方法。从JDK1.2以后,Java提出系统集合框架之后,将Vector改为实现List接口,作为List的实现类之一,从而导致了Vector中存在了一些功能重复的方法。
因此尽量少用Vector,因为能用Vector的地方就能用ArrayList来代替。除此之外,ArrayList与Vector的显著区别是:ArrayList是线程不安全的,Vector是线程安全,所以Vector的性能要比ArrayList要低一些。即使是为了保证List集合的线程安全,同样不推荐使用Vector实现类,后面会介绍Collections工具类,它会是ArrayList变成线程安全的。
Queue集合
Queue用于模拟队列数据结构,队列是遵循“先进先出”,“后进后出”的存储规范。第一个存放的元素对象存放在队列队首位置,后进入的元素插入到队尾的位置,队列不允许随机访问队列中元素。
Queue接口定义的方法:
void add(Object obj):将指定元素加入此队列的尾部。
Object element():获取队列头部的元素,但不删除该元素。
boolean offer(Object obj):将指定元素加入此队列的尾部,当使用有容量限制的队列时,此方法比add()方法更好。
Object peek():获取队列头部的元素,但不删除该元素。如果此队列为空,返回null。
Object poll():获取队列头部的元素,并删除该元素,如果此队列为空,返回Null。
Object remove():获取队列头部的元素,并删除该元素。
PriorityQueue是一个比较标准的Queue实现类,而不是绝对标准的队列实现,是因为PriorityQueue保存队列元素的顺序并不是按照加入队列的顺序进行保存。而是按照队列元素的大小进行重新一次排序。因此使用peek()或者poll()方法获取元素队列位置时,并不一定就是首先存入的元素对象,而是队列中最小的元素。
注意:PriorityQueue不允许插入null值,它需要对队列元素进行排序,PriorityQueue的元素排序分两种情况,自然排序和定制排序,参照TreeSet。
Deque接口是Queue接口的子接口,它代表一个双端队列,Deque接口里定义了一些双端队列的方法,这些方法允许从两端来操作队列元素。
void addFirst(Object obj):将指定元素插入到该队列的首部。
void addlast(Object obj):将指定元素插入到该队列的尾部。
Iterator desceningIterator():返回该双端队列对应的迭代器,该迭代器将以逆向顺序来迭代队列中的元素。
Object getFirst():获取双端队列的第一个元素。
Object getLast():获取双端队列的最后一个元素。
Boolean offerFirst(Object obj):将指定元素插入到双端队列的开头。
Boolean offerLast(Object obj):将指定元素插入到双端队列的末尾。
Object peekFrist():获取但不删除双端队列的第一个元素。
Object peekLast():获取但不删除双端队列的最后一个元素。
Object pollFrist():获取并删除双端队列的第一个元素。
Object pollLast():获取并删除双端队列的最后一个元素。
Object pop():获取并删除该双端队列的第一个元素。
void push(Object obj):将一个元素插入到该双端队列的队首位置,相当于addFrist()
Object removeFirst():获取并删除该双端队列的第一个元素。
Object removeLast():获取并删除该双端队列的最后一个元素。
LinkedList类是List接口的实现类,因此可根据索引来随机访问集合中元素。LinkedList还实现了Deque接口,因此可被当做双端队列来使用,同样也可以被当做“栈”来使用。
LinkedList与ArrayList、ArrayDeque的实现机制不同,ArrayList和ArrayDeque内部以数组的形式来保存集合中元素,因此随机访问集合元素时有较好的性能。而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能不如ArrayList和ArrayDeque。而插入、删除元素时性能非常出色,只需要改变指针所指向的地址即可。
Properties类是Hashtable类的子类,该对象在处理属性文件时非常方便。Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value对写入到属性文件中,也可以把属性文件中的“属性名=属性值”加载到Map对象中。由于属性文件里的属性名、属性值只能是字符串类型,所有Properties里的key、value都是字符串类型。该类的常用方法如下
String getProperty(String key):获取Properties中指定属性名对应的属性值。
String getProperty(String key,String defaultValue):方法重载,获取Properties中指定属性名对应的属性值,如果此属性名不存在时,返回默认的defaultValue值。
Object setProperty(String key,String value):设置属性值,类似于Map的put()方法。
void load(InputStream inStream):从属性文件中加载key-value对。
void store(OutputStream out,String comments):将Properties中的key-value对输入到指定的属性文件中。
属性文件格式:在windows系统下属性文件常以.ini进行结尾,在Java中属性文件以.properties结尾
如同Set接口派生出SortedSet子接口,SortedSet接口有一个实现类TreeSet一样,Map接口也有一个SortedMap接口,SortedMap接口也有一个实现类TreeMap。TreeMap就是一个红黑树数据结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对时,需要根据key对节点进行排序。TreeMap保证所有的key-value对都处于有序的状态。
TreeMap的两种排序方式:
1、自然排序:TreeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则抛出ClassCastException(类型转换异常)。
2、定制排序:创建TreeMap对象时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不需要key实现Comparable接口。

猜你喜欢

转载自blog.csdn.net/qq_39411208/article/details/82181331