不要命的鸡蛋 · List (或ArrayList) ...· 1 月前 · |
打酱油的荒野 · pandas读取excel文件 加快速度 ...· 5 月前 · |
有情有义的小马驹 · python for循环跳过两次怎么写 ...· 1 年前 · |
有腹肌的斑马 · 如何在Vue和Nuxt中构建一个简单的事件总 ...· 1 年前 · |
腹黑的橙子 · Power BI Desktop ...· 1 年前 · |
爽快的大熊猫 · 从0到1复现斯坦福羊驼(Stanford ...· 1 年前 · |
集合框架被设计成要满足以下几个目标。
该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
对一个集合的扩展和适应必须是简单的。
为此,整个集合框架就围绕一组标准接口而设计。你可以直接使用这些接口的标准实现,诸如: LinkedList , HashSet , 和 TreeSet 等,除此之外你也可以通过这些接口实现自己的集合。
从上面的集合框架图可以看到,Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。Collection 接口又有 3 种子类型,List、Set 和 Queue,再下面是一些抽象类,最后是具体实现类,常用的有 ArrayList 、 LinkedList 、 HashSet 、LinkedHashSet、 HashMap 、LinkedHashMap 等等。
集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:
接口:
是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象实现(类): 是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
算法: 是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
除了集合,该框架也定义了几个 Map 接口和类。Map 里存储的是键/值对。尽管 Map 不是集合,但是它们完全整合在集合中。
Java 集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。
集合框架定义了一些接口。本节提供了每个接口的概述:Collection 接口
Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。
Collection 接口存储一组不唯一,无序的对象。
List 接口List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
List 接口存储一组不唯一,有序(插入顺序)的对象。
Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。
Set 接口存储一组唯一,无序的对象。
SortedSetMap 接口存储一组键值对象,提供key(键)到value(值)的映射。
Map.Entry
2. Set 检索效率低下,删除和插入效率高,插入和删除不会引起元素位置改变 <实现类有HashSet,TreeSet> 。
3. List 和数组类似,可以动态增长,根据实际存储的数据的长度自动增长 List 的长度。查找元素效率高,插入删除效率低,因为会引起其他元素位置改变 <实现类有ArrayList,LinkedList,Vector> 。
标准集合类汇总于下表:
AbstractCollectionLinkedList 查找效率低。
ArrayList该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。
LinkedHashSet该类实现了Set接口,可以实现排序等功能。
AbstractMap在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常。当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常。
集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。这些变量都不可改变。
通常情况下,你会希望遍历一个集合中的元素。例如,显示集合中的每个元素。
一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了 Iterator 接口或 ListIterator接口。
迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了 Iterator,以允许双向遍历列表和修改元素。
public class Test { public static void main ( String [ ] args ) { List < String > list = new ArrayList < String > ( ) ; list . add ( " Hello " ) ; list . add ( " World " ) ; list . add ( " HAHAHAHA " ) ; // 第一种遍历方法使用 For-Each 遍历 List for ( String str : list ) { // 也可以改写 for(int i=0;i<list.size();i++) 这种形式 System . out . println ( str ) ; // 第二种遍历,把链表变为数组相关的内容进行遍历 String [ ] strArray = new String [ list . size ( ) ] ; list . toArray ( strArray ) ; for ( int i = 0 ; i < strArray . length ; i ++ ) // 这里也可以改写为 for(String str:strArray) 这种形式 System . out . println ( strArray [ i ] ) ; // 第三种遍历 使用迭代器进行相关遍历 Iterator < String > ite = list . iterator ( ) ; while ( ite . hasNext ( ) ) // 判断下一个元素之后有值 System . out . println ( ite . next ( ) ) ; 三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度。
分享
Com***able@jihe.com
分享
Com***able@jihe.com
影法师
ren***e1@sina.com
有关于 map.entrySet() 和 keySet() :
1、如果遍历 hashMap() 时 entrySet() 方法是将 key 和 value 全部取出来,所以性能开销是可以预计的, 而 keySet() 方法进行遍历的时候是根据取出的 key 值去查询对应的 value 值, 所以如果 key 值是比较简单的结构(如 1,2,3...)的话性能消耗上是比 entrySet() 方法低, 但随着 key 值得复杂度提高 entrySet() 的优势就会显露出来。
2、综合比较在只遍历 key 的时候使用 keySet(), 在只遍历 value 的是使用 values() 方法, 在遍历 key-value 的时候使用 entrySet() 是比较合理的选择。
3、如果遍历 TreeMap 的时候, 不同于 HashMap 在遍历 ThreeMap 的 key-value 时候务必使用 entrySet() 它要远远高于其他两个的性能, 同样只遍历 key 的时候使用 keySet(), 在只遍历 value 的是使用 values() 方法对于 TreeMap 也同样适用。
°
858***854@qq.com
zhangchaohong137
251***396@qq.com
集合还有快速失败(fail—fast)和安全失败(fail—safe)机制,想要深入的话得去了解一下( Java 的快速失败和安全失败 ),解决方法我在此整理一下吧:
1、在单线程的遍历过程中,如果要进行 remove 操作,可以调用迭代器的 remove 方法而不是集合类的 remove 方法。
2、使用 java 并发包(java.util.concurrent)中的类来代替 ArrayList 和 HashMap。比如使用 CopyOnWriterArrayList 代替 ArrayList,CopyOnWriterArrayList 在是使用上跟 ArrayList 几乎一样,CopyOnWriter 是写时复制的容器(COW),在读写时是线程安全的。该容器在对 add 和 remove 等操作时,并不是在原数组上进行修改,而是将原数组拷贝一份,在新数组上进行修改,待完成后,才将指向旧数组的引用指向新数组,所以对于 CopyOnWriterArrayList 在迭代过程并不会发生 fail-fast 现象。但 CopyOnWrite 容器只能保证数据的最终一致性,不能保证数据的实时一致性。对于 HashMap,可以使用 ConcurrentHashMap,ConcurrentHashMap 采用了锁机制,是线程安全的。在迭代方面,ConcurrentHashMap 使用了一种不同的迭代方式。在这种迭代方式中,当 iterator 被创建后集合再发生改变就不再是抛出 ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator 完成后再将头指针替换为新的数据 ,这样 iterator 线程可以使用原来老的数据,而写线程也可以并发的完成改变。即迭代不会发生 fail-fast,但不保证获取的是最新的数据。
zhangchaohong137
251***396@qq.com