摘要:当使用迭代器访问集合元素时,中的元素不能被改变,只能通过的方法删除上一次方法返回的集合元素才可以否则将会引发异常。可以确保集合元素处于有序状态。返回中所有键值对组成的视图,每个集合元素都是是的内部类对象。这种集合称为视图。
1.集合概览
集合包括两大接口:Collection 和 Map。
Map
TreeMap
HashMap
LinkedHashMap
Collection
Set
HashSet
TreeSet
LinkedHashSet
List
ArrayList
LinkedList
Queue
PriorityQueue
Deque
ArrayDeque
LinkedList
集合中常用的四个接口:Comparable, Comparator, Iterable, Iterator。
interface Comparable{ public int compareTo(E obj); } interface Comparator { public int compare(E obj1, E obj2); boolean equals(Object obj); } interface Iterable { Iterator iterator(){}; } interface Iterator { public boolean hasNext(){}; public E next(){}; public void remove(){}; }
remove() 方法可以删除 next() 方法返回的元素,但是不可以连续使用 remove() 方法。因为 Iterator 对象中有一个成员变量 current 保存 next() 方法的返回值,当调用 remove() 删除元素后,current 会被置为 null。所以不能连续调用 remove()。
当使用 Iterator 迭代器访问 Collection 集合元素时,Collection 中的元素不能被改变,只能通过 Iterator 的 remove 方法删除上一次 next 方法返回的集合元素才可以;否则将会引发异常。
Iterator 采用了快速失败(fast-fail)机制,一旦在迭代过程中检测到该集合已经被修改(增加或删除元素),程序立即引发 ConcurrentModifactionException 异常,而不是显示修改后的结果,这样可以避免共享资源而引发的潜在问题。
Collection 接口中定义的方法:也是 Set 的方法
public interface Collectionextends Iterable { int size(); boolean isEmpty(); boolean contains(Object o); //o 是Entry<>对象 Iterator iterator(); Object[] toArray(); T[] toArray(T[] a); boolean add(E e); //当对象存在时,不添加,返回false boolean remove(Object o); //o 是Entry<>对象 boolean containsAll(Collection> c); boolean addAll(Collection extends E> c); boolean removeAll(Collection> c); default boolean removeIf(Predicate super E> filter){ Objects.requireNonNull(filter); boolean removed = false; final Iterator each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } boolean retainAll(Collection> c); void clear(); boolean equals(Object o); int hashCode(); }
AbstractCollection抽象类,它为除 size()和iterator()之外的其他方法提供了默认实现。
Set方法见 Collection 方法
HashSet 中的元素可以是 null 。
HashSet 集合插入和删除元素的过程是:
先调用元素的 hashCode(),计算出元素所在的槽号。
然后在对应槽与链表中的每个结点使用 equals() 方法进行比较,判断是否相等。由于无须判断大小关系。所以不会使用到 Comparable/Comparator 接口。
此外,HashCode 中的 contains(Object),remove(Object) 和 Iterator 中的 remove() 方法都是按照上述方法再对应槽中进行处理。不会遍历整个集合。
TreeSet可以确保集合元素处于有序状态。与 HashSet集合相比,TreeSet还提供了如下几个额外的方法:
Comparator comparator() :如果 TreeSet采用了定制排序,则该方法返回定制排序所用的 Comparator;如果采用自然排序,则返回 null。 Object first():返回集合中的第一个元素。 Object last():返回集合中的最后一个元素。 Object lower(Object e):返回集合中小于指定元素的最大元素,参考元素不需要是 TreeSet集合里的元素。 Object higher(Object e):返回集合中大于指定元素的最小元素,参考元素不需要是TreeSet集合里的元素。 Sorted subSet(Object fromElement, Object toElement):返回此 TreeSet 的子集合,范围从 fromElement(包含)到toElement(不包含)。 Sorted headSet(Object toElement):返回此TreeSet中小于toElement 的元素组成的子集。 Sorted tailSet(Object fromElement):返回此TreeSet中由大于或等于 fromElement 的元素组成的子集。
TreeSet 采用红黑树的数据结构来存储集合元素。在对集合进行遍历时,每个值将按照排序后的顺序呈现。TreeSet 支持两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。如果需要定制排序,需要在创建 TreeSet 对象时,添加 Comparator 对象作为参数。
TreeSet 使用 Comparable/Comparator 来比较元素的大小,以及判断元素是否相等。TreeSet 中元素不可以为 null,因为 null 无法比较大小。
ListList 集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。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):返回对象在 List 集合中第一次出现的位置索引。 int lastIndexOf(Object o):返回对象在List 集合中最后一次出现的位置索引。 Object remove(int index):删除并返回 index 索引处的元素。 Object set(int index , Object element):将 index 处的元素替换成 element对象,返回被替换的就元素。 List subList(int fromIndex,int toIndex):返回从索引 fromIndex(包含)到索引toIndex(不包含)处所有集合元素组成的子集合。 void sort(Comparator c):根据 Comparator 对 List 集合的元素排序。
List 不考虑元素的大小关系,所以通过元素的 equals 方法判断元素是否相等,仅在查找元素时使用。
List 额外提供了一个 listIterator() 方法,该方法返回一个 ListIterator 对象,ListIterator 接口是 Iterator 的子接口,提供了专门操作 List 的方法。ListIterator接口在Iterator 接口基础上增加了如下方法:
boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。 Object previous():返回该迭代器的上一个元素。 void add(Object o) void set(Object o):用一个新元素取代调用 next() 或previous() 返回的上一个元素。 int nextIndex():返回next域所指元素的索引 int previousIndex():返回下一次调用previous 方法时返回元素的索引,即next域索引- 1
iteraotr 中有一个成员 cur 下标,记录遍历的当前位置,
调用 next(),会返回 cur 位置处的元素,并将 cur = cur + 1 or cur = cur.next。
调用 prevoius(),会返回 cur - 1 or cur.previous 处的元素,并将 cur = cur - 1 or cur = cur.previous。
调用 add(),对于 arrayList 而言,会将元素插入 cur 位置处,后面的元素后移一位,且 cur = cur + 1。对于 LinkedList 而言,会将元素插入 cur.previous 处。即会插在 next() 元素的前面, previous() 元素的后面。
Queue新元素插入(offer)到队列的尾部,访问元素(poll)会返回队列头部的元素。通常,队列不允许随机访问队列中的元素。Queue 接口中定义了如下几个方法:
void add(Object e):将指定元素加入此队列的尾部。如果队列满,则抛出异常。 Object remove():获取队列头部的元素,并删除该元素。如果队列为空,则抛出异常。 Object element():获取队列头部的元素,但是不删除该元素。如果队列为空,则抛出异常。 boolean offer(Object e):将指定元素加入此队列的尾部,如果队列满,返回false。 Object poll():获取队列头部的元素,并删除该元素,如果队列为空,则返回null。 Object peek():获取队列头部的元素,但是不删除该元素。如果队列为空,则返回null。
PriorityQueue 内部数据结构是最小堆。PriorityQueue 不允许插入 null 元素,PriorityQueue 的元素有两种排序方式:自然排序和定制排序。
DequeDeque 接口里定义了一些双端队列的方法,这些方法允许从两端来操作队列的元素。
Object getFirst():获取但不删除双端队列的第一个元素。 Object getLast():获取但不删除双端队列的最后一个元素。 Object removeFirst():获取并删除双端队列的第一个元素。 Object removeLast():获取并删除双端队列的最后一个元素。 boolean offerFirst(Object e):将指定元素插入该双端队列的开头。 boolean offerLast(Object e):将指定元素插入该双端队列的末尾。 void addFirst(Object e):将指定元素插入该双端队列的开头。 void addLast(Object e):将指定元素插入该双端队列的尾部。 Object removeFirstOccurrence(Object o):获取并删除双端队列的第一次出现的元素o。 Object removeLastOccurrence(Object o):获取并删除双端队列的最后一次出现的元素o。 Object pollFirst():获取并删除双端队列头部的元素。如果队列为空,则返回null; Object pollLast():获取并删除双端队列尾部的元素。如果队列为空,则返回null; Object peekFirst():获取队列头部的元素,但是不删除该元素。如果队列为空,则返回null; Object peekLast():获取队列尾部的元素,但是不删除该元素。如果队列为空,则返回null; Object pop()(栈方法):pop出该双端队列所表示的栈的栈顶元素。相当于 removeFirst()。 void push(Object e)(栈方法):将一个元素 push 进该双端队列所表示的栈的栈顶。相当于 addFirst(e); Iterator descendingIterator():返回该双端队列对应的迭代器,该迭代器将以逆向顺序来迭代队列中的元素。
实现Deque 接口的类都可以用来作为栈使用,但是实现栈的栈顶是在队列的头部。
Deque 接口提供了一个典型的实现类: ArrayDeque,它是一个基于数组实现的双端队列,创建 Deque 时同样可指定一个 numElements参数,该参数用于指定 Object[] 数组的长度;如果不指定 numElements 参数,Deque 底层数组的长度为16;
LinkdeList 类是 List 接口的实现类 --- 这意味着它是一个 List 集合。除此之外,LinkdeList 还实现了Deque接口,可以被当成双端队列来使用,因此既可以作为栈来使用,也可以作为队列使用。
Map如果把 Map 里的所有 key放在一起,他们组成了一个keySet集合(所有的 key没有顺序,key与 key 之间不能重复)。
如果把 Map 里的所有 value 放在一起来看,他们构成一个 Collection:元素可以重复,每个元素可以根据索引来查找,只是 Map 中的索引不再是下标,而是对应的key。
Map 接口中定义的常用方法有:
int size():返回该Map里的键值对的个数。 void clear():删除该 Map 对象中的所有 key-value对。 boolean isEmpty():查询该Map 是否为空,如果为空,则返回true; boolean containsKey(Object key):查询 Map 中是否包含指定的 key,如果包含则返回true。 boolean containsValue(Object value):查询 Map 中是否包含一个或多个 value,如果包含则返回 true。 V get(Object key):返回指定key 所对应的 value;如果此 Map 中不包含该 key,则返回null。 default V getOrDefault(Object key, V defaultValue):获取与key对应的value,若key不存在,则返回defaultValue V put(K key,V value):添加一个键值对,如果当前 Map 中已有一个相同的key,则用新的键值对覆盖原来的键值对,并返回原来的value。 void putAll(Map<? extends K,? extends V> m):将指定Map中的所有键值对复制到本Map中。 Object remove(Object key):删除指定key对应的键值对,返回被删除key关键的value,如果该key不存在,则返回null; SetkeySet():返回该Map 中所有 key 组成的Set视图。可以从集中删除元素,Map中对应的键值对会被删除,但不能添加元素 Collection values():返回该Map里所有value组成的Collection视图。可以从集合中删除元素(只会删除一个键值对),所删除的值及对应的键将从Map中删除,不能增加元素。 Set > entrySet():返回 Map中所有键值对组成的Set视图,每个集合元素都是 Map.Entry(Entry 是 Map 的内部类)对象。可以从集中删除元素,它们将从映射中删除元素,但不能增加任何元素。
Map 接口中包括一个内部接口 Entry,该接口封装了一个键值对。Entry 包含如下三个方法:
Object getKey():返回该Entry里包含的value值。 Object getVlaue():返回该Entry里包含的value值。 Object setValue(V value):设置该Entry里包含的value值,并返回新设置的alue值
为了成功地在 HashMap 中存储元素,用作key 的对象必须实现 hashCode() 方法 和 equals() 方法。
判断value相等的方法是:使用value的equals()方法返回值来判断。
综上可以,不考虑元素大小序的集合(HashSet,ArrayList,LinkedList,ArrayDeque,HashMap)都是通过 equals() 判断元素是否相等,且允许元素为 null。考虑元素大小关系的集合(TreeSet,PriorityQueue,TreeMap) 都是通过 compareTo/compare() 来判断相等。
Map 有三种视图:keySet、values、entrySet。需要说明的是:keySet 方法返回了一个实现类 Set
如果在键集视图上调用迭代器的 remove() 方法,实际上会从映射中删除这个键对应的键值对。不能向键集试图增加元素,如果试图调用 add(),会抛出异常。entrySet 有同样的限制。
Arrays 的静态方法 asList(Object ... a) 将返回包装了普通数组的 List 包装器。这个方法可以将数组传递给一个期望得到列表或集合参数的方法。它是数组的视图对象,类型为 List<>,带有访问底层数组的 get 和 set 方法。但是改变数组大小的所有方法(例如,与迭代器相关的 add 和 remove 方法)都会抛出异常。
Java 提供了一个操作 Set、List 和 Map 等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了将集合对象设置为不可变、对集合对象实现同步控制等方法。
Collections 提供了如下常用的类方法用于对 List 集合元素进行排序:
void reverse(List list):反转指定 List集合中元素的排序。 void shuffle(List list):对List 集合元素进行随机排序。 void sort(List list):根据元素的自然顺序对指定List集合的元素按升序进行排序。 void sort(List list, Comparator c):根据指定Comparator 产生的顺序对List集合元素进行排序。 void swap(List list, int i,int j):将指定List 集合中的 i处元素和 j处元素进行交换。 void rotate(List list, int distance):当 distance 为正数时,将 list 集合的后 distance个元素“整体”移到前面;当 distance为负数时,将 list集合的前 distance 个元素“整体”移到后面。
Collections 还提供了如下常用的用于查找、替换集合元素的类方法。
int binarySearch(List list, Object key):使用二分搜索大搜索指定的 List集合,以获得指定对象在 List 集合中的索引。如果要使该方法可以正常工作,必须保证 List 中的元素已经处于有序状态。 Object max(Collection coll):根源元素的自然顺序,返回给定集合中的最大元素。 Object max(Collection coll ,Comparator comp):根据Comparator 指定的顺序,返回给定集合中的最大元素。 Object min(Collection coll):根源元素的自然顺序,返回给定集合中的最小元素。 Object min(Collection coll ,Comparator comp):根据Comparator 指定的顺序,返回给定集合中的最小元素。 void fill(List list, Object obj):使用指定元素obj替换指定List集合中的所有元素。 int frequency(Collection c, Object o):返回指定集合中指定元素的出现次数。 int indexOfSubList(List source, List target):返回子 List对象在父 List对象中第一次出现的位置索引;如果父List中没有出现这样的子 List,则返回 -1; int lastIndexOfSubList(List source, List target):返回子 List对象在父 List对象中最后一次出现的位置索引;如果父List中没有出现这样的子 List,则返回 -1; boolean replaceAll(List list, Object olbVal, Object newVal):使用一个新值 newVal 替换 List对象的所有旧值 oldVal。
Collections 类提供了多个 synchromizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。例如:
public class Test{ public static void main(String[] args){ Collection c = Collections.synchronizedCollection(new ArrayList()); List list = Collections.synchronizedList(new ArrayList()); Set s = Collections.synchronizedSet(new ArrayHashSet()); Map m = Collections.synchronizedMap(new HashMap()); } }
在上述程序中,直接将新创建的集合对象传给 Collections 的 synchronizedXxx 方法,这样就可以 直接获取 Set、List、Map 的线程安全实现版本。
集合类 | 插入元素的方法 | 删除元素的方法 | 访问元素的方法 |
---|---|---|---|
List | add(Element),add(index,Element) | remove(index) | get(index) |
Queue | offer(),add() //add添加失败会抛异常 | poll(),remove() //remove失败会抛异常 | peek() |
Set | add(E e) | remove(Object) | |
Map | put(key,value) | remove(key) | get(key) |
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/76822.html
摘要:而在集合中,值仅仅是一个对象罢了该对象对本身而言是无用的。将这篇文章作为集合的总结篇,但觉得没什么好写就回答一些面试题去了,找了一会面试题又觉得不够系统。 前言 声明,本文用的是jdk1.8 花了一个星期,把Java容器核心的知识过了一遍,感觉集合已经无所畏惧了!!(哈哈哈....),现在来总结一下吧~~ 回顾目录: Collection总览 List集合就这么简单【源码剖析】 Ma...
摘要:知识点总结容器知识点总结容器是一个专为枚举设计的集合类,中所有值都必须是指定枚举类型的枚举值,该枚举类型在创建时显式或隐性的指定。集合不容许加入元素。 Java知识点总结(Java容器-EnumSet) @(Java知识点总结)[Java, Java容器, JavaCollection, JavaSet] EnumSet EnumSet是一个专为枚举设计的集合类 ,EnumSet中...
摘要:结构的实例的方法,用于对每个成员执行某种操作,没有返回值。参考和数据结构推荐一个找组件的轮子工厂前端面试总结数据结构与算法一前端面试总结数据结构与算法二前端面试总结数据结构与算法三前端面试总结数据结构与算法四 集合 集合是由一组无序且唯一的项组成。这个数据结构使用了与有限集合相同的数学概念。 创建一个集合 function Set(){ var items = {}; } ...
摘要:前言原文在点这里,这也是作者的个人网站,希望多多支持,对于作者而言,集合主要分为两个派系,一个是系列,一个是系列。的线程安全版本,内部的实现几乎和一模一样。也是的线程安全版本,并且使用了分段加锁机制,所以效率上要比要好很多。 前言 原文在: 点这里,这也是作者的个人网站,希望多多支持,O(∩_∩)O~ 对于作者而言,Java 集合主要分为两个派系,一个是 Collection 系列,一...
阅读 2718·2021-09-01 10:30
阅读 1659·2019-08-30 15:52
阅读 946·2019-08-29 18:40
阅读 1098·2019-08-28 18:30
阅读 2338·2019-08-23 17:19
阅读 1259·2019-08-23 16:25
阅读 2677·2019-08-23 16:18
阅读 2955·2019-08-23 13:53