目录
1.ArrayList集合:该集合在另外一篇博客已有详细叙述。
2.LinkedList集合:是采用链表的结构存储的集合,查询慢,增删快,使用LinkedList特有的方法不能用多态。
3.Vector类:底层也是一个数组,vector是单线程的,速度比较慢
List、Set接口都是属于java.util.Collection<E>接口下的子接口。Collection的子接口与实现类具体如下:
一、List
(一)概述
-
collcetion<E>接口下有List<E>子接口。
-
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制
-
用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
-
与 set 不同,列表通常允许重复的元素。更确切地讲,列表通常允许满足
e1.equals(e2)
的元素对e1
和e2
,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素。难免有人希望通过在用户尝试插入重复元素时抛出运行时异常的方法来禁止重复的列表,但我们希望这种用法越少越好。 -
List
接口在iterator
、add
、remove
、equals
和hashCode
方法的协定上加了一些其他约定,超过了Collection
接口中指定的约定。为方便起见,这里也包括了其他继承方法的声明。 -
List
接口提供了 4 种对列表元素进行定位(索引)访问方法。列表(像 Java 数组一样)是基于 0 的。注意,这些操作可能在和某些实现(例如LinkedList
类)的索引值成比例的时间内执行。因此,如果调用者不知道实现,那么在列表元素上迭代通常优于用索引遍历列表。 -
List
接口提供了特殊的迭代器,称为ListIterator
,除了允许Iterator
接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。 -
List
接口提供了两种搜索指定对象的方法。从性能的观点来看,应该小心使用这些方法。在很多实现中,它们将执行高开销的线性搜索。 -
List
接口提供了两种在列表的任意位置高效插入和移除多个元素的方法。 -
尽管列表允许把自身作为元素包含在内,但建议要特别小心:在这样的列表上,
equals
和hashCode
方法不再是定义良好的。 -
某些列表实现对列表可能包含的元素有限制。例如,某些实现禁止 null 元素,而某些实现则对元素的类型有限制。试图添加不合格的元素会抛出未经检查的异常,通常是
NullPointerException
或ClassCastException
。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在列表中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选” -
综上,List接口有三大特点:1.是一个有序的集合,即存储元素和取出元素的顺序是一致的。2.有索引,包含了一些带索引的方法。3.允许有重复元素。
-
注意事项:操作索引时,一定要防止索引越界。
(二)方法摘要
boolean | add(E e) 向列表的尾部添加指定的元素(可选操作)。 | |
void | add(int index, E element) 在列表的指定位置插入指定元素(可选操作)。 | |
boolean | addAll(Collection<? extends E> c) 添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。 | |
boolean | addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。 | |
void | clear() 从列表中移除所有元素(可选操作)。 | |
boolean | contains(Object o) 如果列表包含指定的元素,则返回 true。 | |
boolean | containsAll(Collection<?> c) 如果列表包含指定 collection 的所有元素,则返回 true。 | |
boolean | equals(Object o) 比较指定的对象与列表是否相等。 | |
E | get(int index) 返回列表中指定位置的元素。 | |
int | hashCode() 返回列表的哈希码值。 | |
int | indexOf(Object o) 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。 | |
boolean | isEmpty() 如果列表不包含元素,则返回 true。 | |
Iterator<E> | iterator() 返回按适当顺序在列表的元素上进行迭代的迭代器。 | |
int | lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。 | |
ListIterator<E> | listIterator() 返回此列表元素的列表迭代器(按适当顺序)。 | |
ListIterator<E> | listIterator(int index) 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。 | |
E | remove(int index) 移除列表中指定位置的元素(可选操作)。 | |
boolean | remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。 | |
boolean | removeAll(Collection<?> c) 从列表中移除指定 collection 中包含的其所有元素(可选操作)。 | |
boolean | retainAll(Collection<?> c) 仅在列表中保留指定 collection 中所包含的元素(可选操作)。 | |
E | set(int index, E element) 用指定元素替换列表中指定位置的元素(可选操作)。 | |
int | size() 返回列表中的元素数。 | |
List<E> | subList(int fromIndex, int toIndex) 返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。 | |
Object[] | toArray() 返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。 | |
| toArray(T[] a) 返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。 |
(三)部分示例
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("a");//[a,b,c,d,a]
list.add(3,"g"); //[a,b,c,g,d,a]
list.remove(2); // [a,b,g,d,a]
list.set(4,"A"); // [a,b,g,d,A],set返回的是被替换的元素,此处返回a
// List的遍历可以使用普通的for循环
for(int i=0;i<list.size();i++){
list.get(i);
}
// 也可以使用迭代器迭代
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
}
// 也可以使用增强for
for(String s:list){
System.out.println(s);
}
// List比较常见的是索引越界异常:IndexOutOfBoundsException
// ArrayIndexOutOfBoundsException 数组索引越界异常
// StringIndexOutOfBoundsException 字符串索引越界异常
(三)List的子接口
1.ArrayList集合:该集合在另外一篇博客已有详细叙述。
2.LinkedList集合:是采用链表的结构存储的集合,查询慢,增删快,使用LinkedList特有的方法不能用多态。
(1)概述
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList
方法来“包装”该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示:
List list = Collections.synchronizedList(new LinkedList(...));
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败 的:在迭代器创建之后,如果从结构上对列表进行修改,除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException
。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。
此类是 Java Collections Framework 的成员。
(2)方法摘要
boolean | add(E e) 将指定元素添加到此列表的结尾。 | |
void | add(int index, E element) 在此列表中指定的位置插入指定的元素。 | |
boolean | addAll(Collection<? extends E> c) 添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。 | |
boolean | addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素从指定位置开始插入此列表。 | |
void | addFirst(E e) 将指定元素插入此列表的开头。 | |
void | addLast(E e) 将指定元素添加到此列表的结尾。 | |
void | clear() 从此列表中移除所有元素。清空后,列表中再取元素会报NoSuchElement方法 | |
Object | clone() 返回此 LinkedList 的浅表副本。 | |
boolean | contains(Object o) 如果此列表包含指定元素,则返回 true。 | |
Iterator<E> | descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。 | |
E | element() 获取但不移除此列表的头(第一个元素)。 | |
E | get(int index) 返回此列表中指定位置处的元素。 | |
E | getFirst() 返回此列表的第一个元素。 | |
E | getLast() 返回此列表的最后一个元素。 | |
int | indexOf(Object o) 返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。 | |
int | lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。 | |
ListIterator<E> | listIterator(int index) 返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始。 | |
boolean | offer(E e) 将指定元素添加到此列表的末尾(最后一个元素)。 | |
boolean | offerFirst(E e) 在此列表的开头插入指定的元素。 | |
boolean | offerLast(E e) 在此列表末尾插入指定的元素。 | |
E | peek() 获取但不移除此列表的头(第一个元素)。 | |
E | peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。 | |
E | peekLast() 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。 | |
E | poll() 获取并移除此列表的头(第一个元素) | |
E | pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 | |
E | pollLast() 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。 | |
E | pop() 从此列表所表示的堆栈处弹出一个元素。 | |
void | push(E e) 将元素推入此列表所表示的堆栈。 | |
E | remove() 获取并移除此列表的头(第一个元素)。 | |
E | remove(int index) 移除此列表中指定位置处的元素。 | |
boolean | remove(Object o) 从此列表中移除首次出现的指定元素(如果存在)。 | |
E | removeFirst() 移除并返回此列表的第一个元素。 | |
boolean | removeFirstOccurrence(Object o) 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。 | |
E | removeLast() 移除并返回此列表的最后一个元素。 | |
boolean | removeLastOccurrence(Object o) 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 | |
E | set(int index, E element) 将此列表中指定位置的元素替换为指定的元素。 | |
int | size() 返回此列表的元素数。 | |
Object[] | toArray() 返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组。 | |
| toArray(T[] a) 返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组;返回数组的运行时类型为指定数组的类型。 |
3.Vector类:底层也是一个数组,vector是单线程的,速度比较慢
(1)概述
Vector
类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector
的大小可以根据需要增大或缩小,以适应创建 Vector
后进行添加或移除项的操作。
每个向量会试图通过维护 capacity
和 capacityIncrement
来优化存储管理。capacity
始终至少应与向量的大小相等;这个值通常比后者大些,因为随着将组件添加到向量中,其存储将按 capacityIncrement
的大小增加存储块。应用程序可以在插入大量组件前增加向量的容量;这样就减少了增加的重分配的量。
由 Vector 的 iterator 和 listIterator 方法所返回的迭代器是快速失败的:如果在迭代器创建后的任意时间从结构上修改了向量(通过迭代器自身的 remove 或 add 方法之外的任何其他方式),则迭代器将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,而不是冒着在将来不确定的时间任意发生不确定行为的风险。Vector 的 elements 方法返回的 Enumeration 不是 快速失败的。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException
。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。
从 Java 2 平台 v1.2 开始,此类改进为可以实现 List
接口,使它成为 Java Collections Framework 的成员。与新 collection 实现不同,Vector
是同步的(单线程的)。
(2)字段摘要
protected int | capacityIncrement 向量的大小大于其容量时,容量自动增加的量。 |
protected int | elementCount Vector 对象中的有效组件数。 |
protected Object[] | elementData 存储向量组件的数组缓冲区。 |
(3)方法摘要
boolean | add(E e) 将指定元素添加到此向量的末尾。 | |
void | add(int index, E element) 在此向量的指定位置插入指定的元素。 | |
boolean | addAll(Collection<? extends E> c) 将指定 Collection 中的所有元素添加到此向量的末尾,按照指定 collection 的迭代器所返回的顺序添加这些元素。 | |
boolean | addAll(int index, Collection<? extends E> c) 在指定位置将指定 Collection 中的所有元素插入到此向量中。 | |
void | addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加 1。 | |
int | capacity() 返回此向量的当前容量。 | |
void | clear() 从此向量中移除所有元素。 | |
Object | clone() 返回向量的一个副本。 | |
boolean | contains(Object o) 如果此向量包含指定的元素,则返回 true 。 | |
boolean | containsAll(Collection<?> c) 如果此向量包含指定 Collection 中的所有元素,则返回 true。 | |
void | copyInto(Object[] anArray) 将此向量的组件复制到指定的数组中。 | |
E | elementAt(int index) 返回指定索引处的组件。 | |
Enumeration<E> | elements() 返回此向量的组件的枚举。 | |
void | ensureCapacity(int minCapacity) 增加此向量的容量(如有必要),以确保其至少能够保存最小容量参数指定的组件数。 | |
boolean | equals(Object o) 比较指定对象与此向量的相等性。 | |
E | firstElement() 返回此向量的第一个组件(位于索引 0 ) 处的项)。 | |
E | get(int index) 返回向量中指定位置的元素。 | |
int | hashCode() 返回此向量的哈希码值。 | |
int | indexOf(Object o) 返回此向量中第一次出现的指定元素的索引,如果此向量不包含该元素,则返回 -1。 | |
int | indexOf(Object o, int index) 返回此向量中第一次出现的指定元素的索引,从 index 处正向搜索,如果未找到该元素,则返回 -1。 | |
void | insertElementAt(E obj, int index) 将指定对象作为此向量中的组件插入到指定的 index 处。 | |
boolean | isEmpty() 测试此向量是否不包含组件。 | |
E | lastElement() 返回此向量的最后一个组件。 | |
int | lastIndexOf(Object o) 返回此向量中最后一次出现的指定元素的索引;如果此向量不包含该元素,则返回 -1。 | |
int | lastIndexOf(Object o, int index) 返回此向量中最后一次出现的指定元素的索引,从 index 处逆向搜索,如果未找到该元素,则返回 -1。 | |
E | remove(int index) 移除此向量中指定位置的元素。 | |
boolean | remove(Object o) 移除此向量中指定元素的第一个匹配项,如果向量不包含该元素,则元素保持不变。 | |
boolean | removeAll(Collection<?> c) 从此向量中移除包含在指定 Collection 中的所有元素。 | |
void | removeAllElements() 从此向量中移除全部组件,并将其大小设置为零。 | |
boolean | removeElement(Object obj) 从此向量中移除变量的第一个(索引最小的)匹配项。 | |
void | removeElementAt(int index) 删除指定索引处的组件。 | |
protected void | removeRange(int fromIndex, int toIndex) 从此 List 中移除其索引位于 fromIndex(包括)与 toIndex(不包括)之间的所有元素。 | |
boolean | retainAll(Collection<?> c) 在此向量中仅保留包含在指定 Collection 中的元素。 | |
E | set(int index, E element) 用指定的元素替换此向量中指定位置处的元素。 | |
void | setElementAt(E obj, int index) 将此向量指定 index 处的组件设置为指定的对象。 | |
void | setSize(int newSize) 设置此向量的大小。 | |
int | size() 返回此向量中的组件数。 | |
List<E> | subList(int fromIndex, int toIndex) 返回此 List 的部分视图,元素范围为从 fromIndex(包括)到 toIndex(不包括)。 | |
Object[] | toArray() 返回一个数组,包含此向量中以恰当顺序存放的所有元素。 | |
| toArray(T[] a) 返回一个数组,包含此向量中以恰当顺序存放的所有元素;返回数组的运行时类型为指定数组的类型。 | |
String | toString() 返回此向量的字符串表示形式,其中包含每个元素的 String 表示形式。 | |
void | trimToSize() 对此向量的容量进行微调,使其等于向量的当前大小。 |
二、set
(一)概述
- 一个不包含重复元素的 collection。更确切地讲,set 不包含满足
e1.equals(e2)
的元素对e1
和e2
,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。 - set存储的数据是无序的,在所有方法里,没有带索引的方法,也不能使用普通的for循环遍历。
- 在所有构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从 Collection 接口所继承的内容。出于方便考虑,它还包括了其他继承方法的声明(这些声明的规范已经专门针对 Set 接口进行了修改,但是没有包含任何其他的规定)。
- 对这些构造方法的其他规定是(不要奇怪),所有构造方法必须创建一个不包含重复元素的 set(正如上面所定义的)。
- 注:如果将可变对象用作 set 元素,那么必须极其小心。如果对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不确定的。此项禁止的一个特殊情况是不允许某个 set 包含其自身作为元素。
- 某些 set 实现对其所包含的元素有所限制。例如,某些实现禁止 null 元素,而某些则对其元素的类型所有限制。试图添加不合格的元素会抛出未经检查的异常,通常是 NullPointerException 或 ClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在 set 中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。
- 主要有两个实现类:HashSet
(二)方法摘要
boolean | add(E e) 如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。 | |
boolean | addAll(Collection<? extends E> c) 如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。 | |
void | clear() 移除此 set 中的所有元素(可选操作)。 | |
boolean | contains(Object o) 如果 set 包含指定的元素,则返回 true。 | |
boolean | containsAll(Collection<?> c) 如果此 set 包含指定 collection 的所有元素,则返回 true。 | |
boolean | equals(Object o) 比较指定对象与此 set 的相等性。 | |
int | hashCode() 返回 set 的哈希码值。 | |
boolean | isEmpty() 如果 set 不包含元素,则返回 true。 | |
Iterator<E> | iterator() 返回在此 set 中的元素上进行迭代的迭代器。 | |
boolean | remove(Object o) 如果 set 中存在指定的元素,则将其移除(可选操作)。 | |
boolean | removeAll(Collection<?> c) 移除 set 中那些包含在指定 collection 中的元素(可选操作)。 | |
boolean | retainAll(Collection<?> c) 仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。 | |
int | size() 返回 set 中的元素数(其容量)。 | |
Object[] | toArray() 返回一个包含 set 中所有元素的数组。 | |
| toArray(T[] a) 返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。 |
(三)子接口
1.HashSet:无序的,不重复的
(1)概述
- 哈希值:一个十进制的整数,由系统随机给出(就是对象的地址,是一个逻辑地址,是模拟得到的,不是数据实际的物理地址)。object类里有个hashCode方法就是获取对象的哈希值。默认的toString方法输出的后面的十六进制值就是对象的hashCode方法取到的值转为16进制数:Integer.toHexString(hashhCode())。
- string类也是对象,重写了hashCode方法,同样的字符串hashCode返回的值是一样的。元素值相同,哈希值不同,称为哈希冲突。
- 此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。哈希表的特点是查询特别快。
- 此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
- 注意,此实现不是同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用
Collections.synchronizedSet
方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问: -
Set s = Collections.synchronizedSet(new HashSet(...));
- 此类的 iterator 方法返回的迭代器是快速失败 的:在创建迭代器之后,如果对 set 进行修改,除非通过迭代器自身的 remove 方法,否则在任何时间以任何方式对其进行修改,Iterator 都将抛出
ConcurrentModificationException
。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来在某个不确定时间发生任意不确定行为的风险。 - 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器在尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误做法:迭代器的快速失败行为应该仅用于检测 bug。
- hashset存储原理:
-
-
hashset元素不重复原理:
(2)构造函数
HashSet() 构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。 |
HashSet(Collection<? extends E> c) 构造一个包含指定 collection 中的元素的新 set。 |
HashSet(int initialCapacity) 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。 |
HashSet(int initialCapacity, float loadFactor) 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子。 |
(3)方法摘要
boolean | add(E e) 如果此 set 中尚未包含指定元素,则添加指定元素。 |
void | clear() 从此 set 中移除所有元素。 |
Object | clone() 返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。 |
boolean | contains(Object o) 如果此 set 包含指定元素,则返回 true。 |
boolean | isEmpty() 如果此 set 不包含任何元素,则返回 true。 |
Iterator<E> | iterator() 返回对此 set 中元素进行迭代的迭代器。 |
boolean | remove(Object o) 如果指定元素存在于此 set 中,则将其移除。 |
int | size() 返回此 set 中的元素的数量(set 的容量)。 |
(4)应用-使用HashSet集合存储自定义类型
例:创建person类,将person对象存储到HashSet中,保证同名同年龄的人只出现一次。实现方法为:重写hashCode()和equals()这两个方法。因为HashSet去重的原理就是依靠这两个函数,即先用hashCode方法判断hash值是否相同,若相同再用equals方法来比较剩下的。
2.LinkedHashSet:有序的,不允许重复
(1)概述
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, Serializable
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在 s.contains(e)返回 true 后立即调用 s.add(e),则元素 e 会被重新插入到 set s 中。)
此实现可以让客户免遭未指定的、由 HashSet
提供的通常杂乱无章的排序工作,而又不致引起与 TreeSet
关联的成本增加。使用它可以生成一个与原来顺序相同的 set 副本,并且与原 set 的实现无关:
void foo(Set s) {
Set copy = new LinkedHashSet(s);
...
}
如果模块通过输入得到一个 set,复制这个 set,然后返回由此副本决定了顺序的结果,这种情况下这项技术特别有用。(客户通常期望内容返回的顺序与它们出现的顺序相同。)
此类提供所有可选的 Set 操作,并且允许 null 元素。与 HashSet 一样,它可以为基本操作(add、contains和 remove)提供稳定的性能,假定哈希函数将元素正确地分布到存储段中。由于增加了维护链接列表的开支,其性能很可能会比 HashSet 稍逊一筹,不过,这一点例外:LinkedHashSet 迭代所需时间与 set 的大小成正比,而与容量无关。HashSet 迭代很可能支出较大,因为它所需迭代时间与其容量 成正比。
链接的哈希 set 有两个影响其性能的参数:初始容量 和加载因子。它们与 HashSet 中的定义极其相同。注意,为初始容量选择非常高的值对此类的影响比对 HashSet 要小,因为此类的迭代时间不受容量的影响。
注意,此实现不是同步的。如果多个线程同时访问链接的哈希 set,而其中至少一个线程修改了该 set,则它必须 保持外部同步。这一般通过对自然封装该 set 的对象进行同步操作来完成。 如果不存在这样的对象,则应该使用 Collections.synchronizedSet
方法来“包装”该 set。最好在创建时完成这一操作,以防止意外的非同步访问:
Set s = Collections.synchronizedSet(new LinkedHashSet(...));
此类的 iterator 方法返回的迭代器是快速失败 的:在迭代器创建之后,如果对 set 进行修改,除非通过迭代器自身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException
。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何强有力的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。
(2)构造方法摘要
LinkedHashSet() 构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set。 |
LinkedHashSet(Collection<? extends E> c) 构造一个与指定 collection 中的元素相同的新链接哈希 set。 |
LinkedHashSet(int initialCapacity) 构造一个带指定初始容量和默认加载因子 (0.75) 的新空链接哈希 set。 |
LinkedHashSet(int initialCapacity, float loadFactor) 构造一个带有指定初始容量和加载因子的新空链接哈希 set。 |
(3)方法摘要:其没有自己独特的方法,都是从父类继承的方法。
三、可变参数
JDK1.5后新增可变参数,即若一个方法需要接受多个参数,且每个参数的类型都是一样的,可以简化写成如下形式:
修饰符 返回值类型 方法名(参数类型... 形参名) { }
以上写法与以下写法完全等价:
修饰符 返回值类型 方法名(参数类型[] 形参名) { }
上述两种的区别主要在于,后者只能传递数组,而前者可以传递数据。
可变参数的主要原理是:可变参数底层就是一个数组,根据传递的参数个数不同,底层创建了不同长度的数组,来存储这些参数,传递的参数个数可以是0个至多个。
注意事项:1.一个方法只能有一个可变参数;2.如果一个方法有多个不同类型的参数,可变参数要写在参数列表的最后。
object类型的可变参数函数可以接受任何参数:int func(object... arr)
四、Collections类:用于操作集合
java.utils.Collections
这个集合中最常用的方法为shuffle、addAll和sort方法
ArrayList<String> arr = new ArrayList<>();
// 往集合中添加一些元素:public static<T> boolean addAll(Collection<T> c,T... Elements)
Collections.addAll(arr,'a','b','c','d');//可以往集合中传递任意多的元素
// 打乱集合中的元素:public static<T> boolean shuffle(List<?> list)
Collections.shuffle(arr);
// 第一种集合排序:public static<T> void sort(List<T> List):将集合中的元素按照默认顺序排序.默认顺序是指升序。字母则按照a b c这个顺序为默认顺序。
ArrList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
list01.add(3);
list01.add(4);
Collections.sort(list01);
// 对于对象类型的数据,如果要使用sort方法,需要实现Comparable<E>接口,并重写compareTo的方法。字符串的类就是重写了这个方法。
class Person implements Comparable<Person>{
private String name;
private int age;
public int getAge(){
return this.age;
}
// 重写排序规则
public int compareTo(Person o){
return this.getAge()-o.getAge();//这样的话就是按照年龄升序排序。// this减去参数就是升序
}
}
ArrList<Person> list02 = new ArrayList<>();
list02.add(new Person("ab",18));
list02.add(new Person("cd",28));
list02.add(new Person("ef",38));
Collections.sort(list02);
// 第二种集合排序,即将集合中的元素按照指定的规则进行排序
// public static <T> void sort(List<T> list,Comparator<? super T>)
// comparator相当于找一个第三方的裁判来比较两个人,重写Comparator接口中的compare方法。
Collections.sort(list01,new Comparator<Integer>(){
@override
public int compare(Integer o1,Integer o2){
return o1-o2;//升序排列,compare函数的前面参数减去后面参数就是升序排序
}
});
// 同理比较两个自定义类,也通过重写compare方法实现。