简化图:
解释:对付以上的框架图有如下几点解释
1、所有凑集类都位于java.util包下。Java 的凑集类紧张由两个接口派生而出:Collection 和 Map,Collection 和 Map 是 Java 凑集框架的根接口,这两个接口又包含了一些子接口或实现类。

2、凑集接口:6 个接口(短虚线表示),表示不同凑集类型,是凑集框架的根本。
3、抽象类:5 个抽象类(长虚线表示),对凑集接口的部分实现。可扩展为自定义凑集类。
4、实现类:8 个实现类(实线表示),对接口的详细实现。
5、Collection 接口是一组许可重复的工具。
6、Set 接口继续 Collection,凑集元素不重复。
7、List 接口继续 Collection,许可重复,掩护元素插入顺序。
8、Map 接口是键-值工具,与 Collection 接口没有什么关系。
9、Set、List 和 Map 可以看做凑集的三大类:
List 凑集是有序凑集,凑集中的元素可以重复,访问凑集中的元素可以根据元素的索引来访问。Set 凑集是无序凑集,凑集中的元素不可以重复,访问凑集中的元素只能根据元素本身来访问(也是凑集里元素不许可重复的缘故原由)。Map 凑集中保存 Key-value 对形式的元素,访问时只能根据每项元素的 key 来访问其 value。二、总体剖析大致解释:
看上面的框架图,先捉住它的主干,即 Collection 和 Map。
1、Collection 是一个接口,是高度抽象出来的凑集,它包含了凑集的基本操作和属性。Collection 包含了 List 和 Set 两大分支。
List 是一个有序的行列步队,每一个元素都有它的索引。第一个元素的索引值是 0。List 的实现类有 LinkedList, ArrayList, Vector, Stack。Set 是一个不许可有重复元素的凑集。Set 的实现类有 HastSet 和 TreeSet。HashSet 依赖于 HashMap,它实际上是通过 HashMap 实现的;TreeSet 依赖于 TreeMap,它实际上是通过 TreeMap 实现的。2、Map 是一个映射接口,即 key-value 键值对。Map 中的每一个元素包含 “一个 key” 和“key 对应的 value”。AbstractMap 是个抽象类,它实现了 Map 接口中的大部分 API。而 HashMap,TreeMap,WeakHashMap 都是继续于 AbstractMap。Hashtable 虽然继续于 Dictionary,但它实现了 Map 接口。
3、接下来,再看 Iterator。它是遍历凑集的工具,即我们常日通过 Iterator 迭代器来遍历凑集。我们说 Collection 依赖于 Iterator,是由于 Collection 的实现类都要实现 iterator() 函数,返回一个 Iterator 工具。ListIterator 是专门为遍历 List 而存在的。
4、再看 Enumeration,它是 JDK 1.0 引入的抽象类。浸染和 Iterator 一样,也是遍历凑集;但是 Enumeration 的功能要比 Iterator 少。在上面的框图中,Enumeration 只能在 Hashtable, Vector, Stack 中利用。
5、末了,看 Arrays 和 Collections。它们是操作数组、凑集的两个工具类。
搜索公纵号:MarkerHub,关注回答[ vue ]获取前后端入门教程!
有了上面的整体框架之后,我们接下来对每个类分别进行剖析。
三、Collection 接口Collection 接口是处理工具凑集的根接口,个中定义了很多对元素进行操作的方法。Collection 接口有两个紧张的子接口 List 和 Set,把稳 Map 不是 Collection 的子接口,这个要牢记。
Collection 接口中的方法如下:
个中,有几个比较常用的方法,比如方法 add() 添加一个元素到凑集中,addAll() 将指定凑集中的所有元素添加到凑集中,contains()方法检测凑集中是否包含指定的元素,toArray() 方法返回一个表示凑集的数组。
其余,Collection 中有一个iterator()函数,它的浸染是返回一个 Iterator 接口。常日,我们通过 Iterator 迭代器来遍历凑集。ListIterator 是 List 接口所特有的,在 List 接口中,通过ListIterator()返回一个 ListIterator 工具。
Collection 接口有两个常用的子接口,下面详细先容。
1.List 接口List 凑集代表一个有序凑集,凑集中每个元素都有其对应的顺序索引。List 凑集许可利用重复元素,可以通过索引来访问指定位置的凑集元素。
List 接口继续于 Collection 接口,它可以定义一个许可重复的有序凑集。由于 List 中的元素是有序的,以是我们可以通过利用索引(元素在 List 中的位置,类似于数组下标)来访问 List 中的元素,这类似于 Java 的数组。
List 接口为 Collection 直接接口。List 所代表的是有序的 Collection,即它用某种特定的插入顺序来掩护元素顺序。用户可以对列表中每个元素的插入位置进行精确地掌握,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。实现 List 接口的凑集紧张有:ArrayList、LinkedList、Vector、Stack。
(1)ArrayListArrayList 是一个动态数组,也是我们最常用的凑集。它许可任何符合规则的元素插入乃至包括 null。每一个 ArrayList 都有一个初始容量(10),该容量代表了数组的大小。随着容器中的元素不断增加,容器的大小也会随着增加。在每次向容器中增加元素的同时都会进行容量检讨,当快溢出时,就会进行扩容操作。以是如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而摧残浪费蹂躏韶光、效率。
size、isEmpty、get、set、iterator和 listIterator 操作都以固定时间运行。add 操作以分摊的固定时间运行,也便是说,添加 n 个元素须要 O(n) 韶光(由于要考虑到扩容,以是这不但是添加元素会带来分摊固定时间开销那样大略)。
ArrayList 善于于随机访问。同时 ArrayList 是非同步的。
(2)LinkedList同样实现 List 接口的 LinkedList 与 ArrayList 不同,ArrayList 是一个动态数组,而 LinkedList 是一个双向链表。以是它除了有 ArrayList 的基本操作方法外还额外供应了get,remove,insert方法在 LinkedList 的首部或尾部。
由于实现的办法不同,LinkedList 不能随机访问,它所有的操作都是要按照双重链表的须要实行。在列表中索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。这样做的好处便是可以通过较低的代价在 List 中进行插入和删除操作。
与 ArrayList 一样,LinkedList 也是非同步的。如果多个线程同时访问一个 List,则必须自己实现访问同步。一种办理方法是在创建 List 时布局一个同步的 List:
Listlist=Collections.synchronizedList(newLinkedList(...));
(3)Vector
与 ArrayList 相似,但是 Vector 是同步的。以是说 Vector 是线程安全的动态数组。它的操作与 ArrayList 险些一样。
(4)StackStack 继续自 Vector,实现一个后进先出的堆栈。Stack 供应 5 个额外的方法使得 Vector 得以被当作堆栈利用。基本的 push 和 pop 方法,还有 peek 方法得到栈顶的元素,empty 方法测试堆栈是否为空,search 方法检测一个元素在堆栈中的位置。Stack 刚创建后是空栈。
2.Set 接口
Set 是一种不包括重复元素的 Collection。它坚持它自己的内部排序,以是随机访问没有任何意义。与 List 一样,它同样许可 null 的存在但是仅有一个。由于 Set 接口的分外性,所有传入 Set 凑集中的元素都必须不同,同时要把稳任何可变工具,如果在对凑集中元素进行操作时,导致e1.equals(e2)==true,则必定会产生某些问题。Set 接口有三个详细实现类,分别是散列集 HashSet、链式散列集 LinkedHashSet 和树形集 TreeSet。
搜索公纵号:MarkerHub,关注回答[ vue ]获取前后端入门教程!
Set 是一种不包含重复的元素的 Collection,无序,即任意的两个元素 e1 和 e2 都有 e1.equals(e2)=false,Set 最多有一个 null 元素。
须要把稳的是:虽然 Set 中元素没有顺序,但是元素在 set 中的位置是由该元素的 HashCode 决定的,其详细位置实在是固定的。
此外须要解释一点,在 set 接口中的不重复是有分外哀求的。
举一个例子:工具 A 和工具 B,本来是不同的两个工具,正常情形下它们是能够放入到 Set 里面的,但是如果工具 A 和 B 的都重写了 hashcode 和 equals 方法,并且重写后的 hashcode 和 equals 方法是相同的话。那么 A 和 B 是不能同时放入到 Set 凑集中去的,也便是 Set 凑集中的去重和 hashcode 与 equals 方法直接干系。
为了更好地理解,请看下面的例子:
publicclassTest{publicstaticvoidmain(String[]args){Set<String>set=newHashSet<String>();set.add("Hello");set.add("world");set.add("Hello");System.out.println("凑集的尺寸为:"+set.size());System.out.println("凑集中的元素为:"+set.toString());}}
运行结果:
凑集的尺寸为: 2凑集中的元素为:[world, Hello]
剖析:由于 String 类中重写了 hashcode 和 equals 方法,用来比较指向的字符串工具所存储的字符串是否相等。以是这里的第二个 Hello 是加不进去的。
再看一个例子:
publicclassTestSet{publicstaticvoidmain(String[]args){Set<String>books=newHashSet<String>();//添加一个字符串工具books.add(newString("Struts2威信指南"));//再次添加一个字符串工具,//由于两个字符串工具通过equals方法比较相等,以是添加失落败,返回falsebooleanresult=books.add(newString("Struts2威信指南"));System.out.println(result);//下面输出看到凑集只有一个元素System.out.println(books);}}
运行结果:
false[Struts2 威信指南]
解释:程序中,book 凑集两次添加的字符串工具明显不是一个工具(程序通过 new 关键字来创建字符串工具),当利用 == 运算符判断返回 false,利用 equals 方法比较返回 true,以是不能添加到 Set 凑集中,末了只能输出一个元素。
(1)HashSetHashSet 是一个没有重复元素的凑集。它是由 HashMap 实现的,不担保元素的顺序 (这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致),而且 HashSet 许可利用 null 元素。HashSet 是非同步的,如果多个线程同时访问一个哈希 set,而个中至少一个线程修正了该 set,那么它必须保持外部同步。 HashSet 按 Hash 算法来存储凑集的元素,因此具有很好的存取和查找性能。
HashSet 的实现办法大致如下,通过一个 HashMap 存储元素,元素是存放在 HashMap 的 Key 中,而 Value 统一利用一个 Object 工具。
HashSet 利用和理解中随意马虎涌现的误区:
a.HashSet 中存放 null 值。HashSet 中是许可存入 null 值的,但是在 HashSet 中仅仅能够存入一个 null 值。
b.HashSet 中存储元素的位置是固定的。HashSet 中存储的元素的是无序的,这个没什么好说的,但是由于 HashSet 底层是基于 Hash 算法实现的,利用了 hashcode,以是 HashSet 中相应的元素的位置是固定的。
c. 必须小心操作可变工具(Mutable Object)。如果一个 Set 中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
(2)LinkedHashSetLinkedHashSet 继续自 HashSet,其底层是基于 LinkedHashMap 来实现的,有序,非同步。LinkedHashSet 凑集同样是根据元素的 hashCode 值来决定元素的存储位置,但是它同时利用链表掩护元素的次序。这样使得元素看起来像因此插入顺序保存的,也便是说,当遍历该凑集时候,LinkedHashSet 将会以元素的添加顺序访问凑集的元素。
(3)TreeSetTreeSet 是一个有序凑集,其底层是基于 TreeMap 实现的,非线程安全。TreeSet 可以确保凑集元素处于排序状态。TreeSet 支持两种排序办法,自然排序和定制排序,个中自然排序为默认的排序办法。当我们布局 TreeSet 时,若利用不带参数的布局函数,则 TreeSet 的利用自然比较器;若用户须要利用自定义的比较器,则须要利用带比较器的参数。
把稳:TreeSet 凑集不是通过 hashcode 和 equals 函数来比较元素的. 它是通过 compare 或者 comparaeTo 函数来判断元素是否相等. compare 函数通过判断两个工具的 id,相同的 id 判断为重复元素,不会被加入到凑集中。
四、Map 接口Map 与 List、Set 接口不同,它是由一系列键值对组成的凑集,供应了 key 到 Value 的映射。同时它也没有继续 Collection。在 Map 中它担保了 key 与 value 之间的逐一对应关系。也便是说一个 key 对应一个 value,以是它不能存在相同的 key 值,当然 value 值可以相同。
1.HashMap以哈希表数据构造实现,查找工具时通过哈希函数打算其位置,它是为快速查询而设计的,其内部定义了一个 hash 表数组(Entry[] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,如果有冲突,则利用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看 HashMap.Entry 的源码它是一个单链表构造。
2.LinkedHashMapLinkedHashMap 是 HashMap 的一个子类,它保留插入的顺序,如果须要输出的顺序和输入时的相同,那么就选用 LinkedHashMap。
LinkedHashMap 是 Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现供应所有可选的映射操作,并许可利用 null 值和 null 键。此类不担保映射的顺序,特殊是它不担保该顺序历久不变。
LinkedHashMap 实现与 HashMap 的不同之处在于,后者掩护着一个运行于所有条款标双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序 (调用 get 方法) 的链表。默认是按插入顺序排序,如果指定按访问顺序排序,那么调用 get 方法后,会将这次访问的元素移至链表尾部,不断访问可以形成按访问顺序排序的链表。
把稳,此实现不是同步的。如果多个线程同时访问链接的哈希映射,而个中至少一个线程从构造上修正了该映射,则它必须保持外部同步。由于 LinkedHashMap 须要掩护元素的插入顺序,因此性能略低于 HashMap 的性能,但在迭代访问 Map 里的全部元素时将有很好的性能,由于它以链表来掩护内部顺序。
3.TreeMap
TreeMap 是一个有序的 key-value 凑集,非同步,基于红黑树(Red-Black tree)实现,每一个 key-value 节点作为红黑树的一个节点。TreeMap 存储时会进行排序的,会根据 key 来对 key-value 键值对进行排序,个中排序办法也是分为两种,一种是自然排序,一种是定制排序,详细取决于利用的布局方法。
自然排序:TreeMap 中所有的 key 必须实现 Comparable 接口,并且所有的 key 都该当是同一个类的工具,否则会报 ClassCastException 非常。
定制排序:定义 TreeMap 时,创建一个 comparator 工具,该工具对所有的 treeMap 中所有的 key 值进行排序,采取定制排序的时候不须要 TreeMap 中所有的 key 必须实现 Comparable 接口。
TreeMap 判断两个元素相等的标准:两个 key 通过compareTo()方法返回 0,则认为这两个 key 相等。
如果利用自定义的类来作为 TreeMap 中的 key 值,且想让 TreeMap 能够良好的事情,则必须重写自定义类中的equals()方法,TreeMap 中止定相等的标准是:两个 key 通过equals()方法返回为 true,并且通过compareTo()方法比较该当返回为 0。
五、Iterator 与 ListIterator 详解1.Iterator
Iterator 的定义如下:
publicinterfaceIterator<E>{}
Iterator 是一个接口,它是凑集的迭代器。凑集可以通过 Iterator 去遍历凑集中的元素。
Iterator 供应的 API 接口如下:
boolean hasNext():判断凑集里是否存不才一个元素。如果有,hasNext() 方法返回 true。Object next():返回凑集里下一个元素。void remove():删除凑集里上一次 next 方法返回的元素。利用示例:
publicclassIteratorExample{publicstaticvoidmain(String[]args){ArrayList<String>a=newArrayList<String>();a.add("aaa");a.add("bbb");a.add("ccc");System.out.println("Beforeiterate:"+a);Iterator<String>it=a.iterator();while(it.hasNext()){Stringt=it.next();if("bbb".equals(t)){it.remove();}}System.out.println("Afteriterate:"+a);}}
输出结果如下:
Before iterate : [aaa, bbb, ccc]After iterate : [aaa, ccc]
把稳:Iterator 只能单向移动。Iterator.remove() 是唯一安全的办法来在迭代过程中修正凑集;如果在迭代过程中以任何其它的办法修正了基本凑集将会产生未知的行为。而且每调用一次next()方法,remove()方法只能被调用一次,如果违反这个规则将抛出一个非常。2.ListIteratorListIterator 是一个功能更加强大的迭代器, 它继续于 Iterator 接口,只能用于各种 List 类型的访问。可以通过调用listIterator()方法产生一个指向 List 开始处的 ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为 n 的元素处的 ListIterator。
ListIterator 接口定义如下:
publicinterfaceListIterator<E>extendsIterator<E>{booleanhasNext();Enext();booleanhasPrevious();Eprevious();intnextIndex();intpreviousIndex();voidremove();voidset(Ee);voidadd(Ee);}
由以上定义我们可以推出 ListIterator 可以:
双向移动(向前 / 向后遍历).产生相对付迭代器在列表中指向确当前位置的前一个和后一个元素的索引.可以利用set()方法更换它访问过的末了一个元素.可以利用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素.利用示例:
publicclassListIteratorExample{publicstaticvoidmain(String[]args){ArrayList<String>a=newArrayList<String>();a.add("aaa");a.add("bbb");a.add("ccc");System.out.println("Beforeiterate:"+a);ListIterator<String>it=a.listIterator();while(it.hasNext()){System.out.println(it.next()+","+it.previousIndex()+","+it.nextIndex());}while(it.hasPrevious()){System.out.print(it.previous()+"");}System.out.println();it=a.listIterator(1);while(it.hasNext()){Stringt=it.next();System.out.println(t);if("ccc".equals(t)){it.set("nnn");}else{it.add("kkk");}}System.out.println("Afteriterate:"+a);}}
输出结果如下:
Beforeiterate:[aaa,bbb,ccc]aaa,0,1bbb,1,2ccc,2,3cccbbbaaabbbcccAfteriterate:[aaa,bbb,kkk,nnn]
六、异同点1.ArrayList 和 LinkedListArrayList 是实现了基于动态数组的数据构造,LinkedList 基于链表的数据构造。对付随机访问 get 和 set,ArrayList 绝对优于 LinkedList,由于 LinkedList 要移动指针。对付新增和删除操作 add 和 remove,LinedList 比较占上风,由于 ArrayList 要移动数据。
这一点要看实际情形的。若只对单条数据插入或删除,ArrayList 的速率反而优于 LinkedList。但若是批量随机的插入删除数据,LinkedList 的速率大大优于 ArrayList. 由于 ArrayList 每插入一条数据,要移动插入点及之后的所有数据。
2.HashTable 与 HashMap相同点:
都实现了Map、Cloneable、java.io.Serializable接口。都是存储 "键值对 (key-value)" 的散列表,而且都是采取拉链法实现的。不同点:
(1)历史缘故原由:HashTable 是基于迂腐的 Dictionary 类的,HashMap 是 Java 1.2 引进的 Map 接口的一个实现 。
(2)同步性:HashTable 是线程安全的,也便是说是同步的,而 HashMap 是线程序不屈安的,不是同步的 。
(3)对 null 值的处理:HashMap 的 key、value 都可为 null,HashTable 的 key、value 都不可为 null 。
(4)基类不同:HashMap 继续于 AbstractMap,而 Hashtable 继续于 Dictionary。
Dictionary 是一个抽象类,它直接继续于 Object 类,没有实现任何接口。Dictionary 类是 JDK 1.0 的引入的。虽然 Dictionary 也支持 “添加 key-value 键值对”、“获取 value”、“获取大小” 等基本操作,但它的 API 函数比 Map 少;而且 Dictionary 一样平常是通过 Enumeration(列举类)去遍历,Map 则是通过 Iterator(迭代 M 器)去遍历。然而由于 Hashtable 也实现了 Map 接口,以是,它即支持 Enumeration 遍历,也支持 Iterator 遍历。AbstractMap 是一个抽象类,它实现了 Map 接口的绝大部分 API 函数;为 Map 的详细实现类供应了极大的便利。它是 JDK 1.2 新增的类。(5)支持的遍历种类不同:HashMap 只支持 Iterator(迭代器) 遍历。而 Hashtable 支持 Iterator(迭代器) 和 Enumeration(列举器) 两种办法遍历。
3.HashMap、Hashtable、LinkedHashMap 和 TreeMap 比较Hashmap 是一个最常用的 Map,它根据键的 HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速率。遍历时,取得数据的顺序是完备随机的。HashMap 最多只许可一条记录的键为 Null;许可多条记录的值为 Null;HashMap 不支持线程的同步,即任一时候可以有多个线程同时写 HashMap;可能会导致数据的不一致。如果须要同步,可以用 Collections 的 synchronizedMap 方法使 HashMap 具有同步的能力。
Hashtable 与 HashMap 类似,不同的是:它不许可记录的键或者值为空;它支持线程的同步,即任一时候只有一个线程能写 Hashtable,因此也导致了 Hashtale 在写入时会比较慢。
LinkedHashMap 保存了记录的插入顺序,在用 Iterator 遍历 LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在布局时用带参数,按照运用次数排序。在遍历的时候会比 HashMap 慢,不过有种情形例外,当 HashMap 容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap 慢,由于 LinkedHashMap 的遍历速率只和实际数据有关,和容量无关,而 HashMap 的遍历速率和他的容量有关。
如果须要输出的顺序和输入的相同,那么用 LinkedHashMap 可以实现,它还可以按读取顺序来排列,像连接池中可以运用。LinkedHashMap 实现与 HashMap 的不同之处在于,后者掩护着一个运行于所有条款标双重链表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。对付 LinkedHashMap 而言,它继续与 HashMap、底层利用哈希表与双向链表来保存所有元素。其基本操作与父类 HashMap 相似,它通过重写父类干系的方法,来实现自己的链接列表特性。
TreeMap 实现 SortMap 接口,内部实现是红黑树。能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。TreeMap 不许可 key 的值为 null。非同步的。
一样平常情形下,我们用的最多的是 HashMap,HashMap 里面存入的键值对在取出的时候是随机的,它根据键的 HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速率。在 Map 中插入、删除和定位元素,HashMap 是最好的选择。
TreeMap 取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么 TreeMap 会更好。
LinkedHashMap 是 HashMap 的一个子类,如果须要输出的顺序和输入的相同,那么用 LinkedHashMap 可以实现,它还可以按读取顺序来排列,像连接池中可以运用。
importjava.util.HashMap;importjava.util.Iterator;importjava.util.LinkedHashMap;importjava.util.TreeMap;publicclassMapTest{publicstaticvoidmain(String[]args){//HashMapHashMap<String,String>hashMap=newHashMap();hashMap.put("4","d");hashMap.put("3","c");hashMap.put("2","b");hashMap.put("1","a");Iterator<String>iteratorHashMap=hashMap.keySet().iterator();System.out.println("HashMap-->");while(iteratorHashMap.hasNext()){Objectkey1=iteratorHashMap.next();System.out.println(key1+"--"+hashMap.get(key1));}//LinkedHashMapLinkedHashMap<String,String>linkedHashMap=newLinkedHashMap();linkedHashMap.put("4","d");linkedHashMap.put("3","c");linkedHashMap.put("2","b");linkedHashMap.put("1","a");Iterator<String>iteratorLinkedHashMap=linkedHashMap.keySet().iterator();System.out.println("LinkedHashMap-->");while(iteratorLinkedHashMap.hasNext()){Objectkey2=iteratorLinkedHashMap.next();System.out.println(key2+"--"+linkedHashMap.get(key2));}//TreeMapTreeMap<String,String>treeMap=newTreeMap();treeMap.put("4","d");treeMap.put("3","c");treeMap.put("2","b");treeMap.put("1","a");Iterator<String>iteratorTreeMap=treeMap.keySet().iterator();System.out.println("TreeMap-->");while(iteratorTreeMap.hasNext()){Objectkey3=iteratorTreeMap.next();System.out.println(key3+"--"+treeMap.get(key3));}}}
输出结果:
HashMap-->3--c2--b1--a4--dLinkedHashMap-->4--d3--c2--b1--aTreeMap-->1--a2--b3--c4--d
4.HashSet、LinkedHashSet、TreeSet 比较Set 接口
Set 不许可包含相同的元素,如果试图把两个相同元素加入同一个凑集中,add 方法返回 false。
Set 判断两个工具相同不是利用 == 运算符,而是根据 equals 方法。也便是说,只要两个工具用 equals 方法比较返回 true,Set 就不会接管这两个工具。
HashSetHashSet 有以下特点:
不能担保元素的排列顺序,顺序有可能发生变革。不是同步的。凑集元素可以是 null,但只能放入一个 null。当向 HashSet 结合中存入一个元素时,HashSet 会调用该工具的 hashCode() 方法来得到该工具的 hashCode 值,然后根据 hashCode 值来决定该工具在 HashSet 中存储位置。大略的说,HashSet 凑集判断两个元素相等的标准是两个工具通过 equals 方法比较相等,并且两个工具的 hashCode() 方法返回值也相等。
把稳,如果要把一个工具放入 HashSet 中,重写该工具对应类的 equals 方法,也该当重写其 hashCode() 方法。其规则是如果两个工具通过 equals 方法比较返回 true 时,其 hashCode 也该当相同。其余,工具中用作 equals 比较标准的属性,都该当用来打算 hashCode 的值。
LinkedHashSetLinkedHashSet 凑集同样是根据元素的 hashCode 值来决定元素的存储位置,但是它同时利用链表掩护元素的次序。这样使得元素看起来像因此插入顺序保存的,也便是说,当遍历该凑集时候,LinkedHashSet 将会以元素的添加顺序访问凑集的元素。
LinkedHashSet 在迭代访问 Set 中的全部元素时,性能比 HashSet 好,但是插入时性能轻微逊色于 HashSet。
TreeSet 类TreeSet 是 SortedSet 接口的唯一实现类,TreeSet 可以确保凑集元素处于排序状态。TreeSet 支持两种排序办法,自然排序和定制排序,个中自然排序为默认的排序办法。向 TreeSet 中加入的该当是同一个类的工具。
TreeSet 判断两个工具不相等的办法是两个工具通过 equals 方法返回 false,或者通过 CompareTo 方法比较没有返回 0。
自然排序
自然排序利用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。
Java 供应了一个 Comparable 接口,该接口里定义了一个compareTo(Object obj)方法,该方法返回一个整数值,实现了该接口的工具就可以比较大小。obj1.compareTo(obj2)方法如果返回 0,则解释被比较的两个工具相等,如果返回一个正数,则表明 obj1 大于 obj2,如果是负数,则表明 obj1 小于 obj2。如果我们将两个工具的 equals 方法总是返回 true,则这两个工具的 compareTo 方法返回该当返回 0。
定制排序
自然排序是根据凑集元素的大小,以升序排列,如果要定制排序,该当利用 Comparator 接口,实现 int compare(T o1,T o2)方法。
packagecom.test;importjava.util.HashSet;importjava.util.LinkedHashSet;importjava.util.TreeSet;/@description几个set的比较 HashSet:哈希表是通过利用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放; LinkedHashSet:以元素插入的顺序来掩护凑集的链接表,许可以插入的顺序在凑集中迭代; TreeSet:供应一个利用树构造存储Set接口的实现,工具以升序顺序存储,访问和遍历的韶光很快。@authorZhou-Jingxian/publicclassSetDemo{publicstaticvoidmain(String[]args){HashSet<String>hs=newHashSet<String>();hs.add("B");hs.add("A");hs.add("D");hs.add("E");hs.add("C");hs.add("F");System.out.println("HashSet顺序:\n"+hs);LinkedHashSet<String>lhs=newLinkedHashSet<String>();lhs.add("B");lhs.add("A");lhs.add("D");lhs.add("E");lhs.add("C");lhs.add("F");System.out.println("LinkedHashSet顺序:\n"+lhs);TreeSet<String>ts=newTreeSet<String>();ts.add("B");ts.add("A");ts.add("D");ts.add("E");ts.add("C");ts.add("F");System.out.println("TreeSet顺序:\n"+ts);}}
输出结果:
HashSet顺序:[D,E,F,A,B,C]LinkedHashSet顺序:[B,A,D,E,C,F]TreeSet顺序:[A,B,C,D,E,F]
5、Iterator 和 ListIterator 差异
我们在利用 List,Set 的时候,为了实现对其数据的遍历,我们常常利用到了 Iterator(迭代器)。利用迭代器,你不须要干涉其遍历的过程,只须要每次取出一个你想要的数据进行处理就可以了。但是在利用的时候也是有不同的。
List 和 Set 都有iterator()来取得其迭代器。对 List 来说,你也可以通过 listIterator() 取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator 和 ListIterator 紧张差异在以下方面:
ListIterator 有add()方法,可以向 List 中添加工具,而 Iterator 不能ListIterator 和 Iterator 都有hasNext()和next()方法,可以实现顺序向后遍历,但是 ListIterator 有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator 就不可以。ListIterator 可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator 没有此功能。都可实现删除工具,但是 ListIterator 可以实现工具的修正,set()方法可以实现。Iierator 仅能遍历,不能修正。由于 ListIterator 的这些功能,可以实现对 LinkedList 等 List 数据构造的操作。实在,数组工具也可以用迭代器来实现。
6、Collection 和 Collections 差异(1)java.util.Collection 是一个凑集接口(凑集类的一个顶级接口)。它供应了对凑集工具进行基本操作的通用接口方法。Collection 接口在 Java 类库中有很多详细的实现。Collection 接口的意义是为各种详细的凑集供应了最大化的统一操作办法,其直接继续接口有 List 与 Set。
Collection├List│├LinkedList│├ArrayList│└Vector│ └Stack└Set
(2)java.util.Collections 是一个包装类(工具类 / 帮助类)。它包含有各种有关凑集操作的静态多态方法。此类不能实例化,就像一个工具类,用于对凑集中元素进行排序、搜索以及线程安全等各种操作,做事于 Java 的 Collection 框架。
代码示例:
importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;publicclassTestCollections{publicstaticvoidmain(Stringargs[]){//把稳List是实现Collection接口的Listlist=newArrayList();doublearray[]={112,111,23,456,231};for(inti=0;i<array.length;i++){list.add(newDouble(array[i]));}Collections.sort(list);for(inti=0;i<array.length;i++){System.out.println(list.get(i));}//结果:23.0 111.0 112.0 231.0 456.0}}