目录
一、Java 集合框架体系
1.Collection接口:用于存储一个一个的数据,也称单列数据集合(single)。
2.Map接口:用于存储具有映射关系“key-value对”的集合(couple)
3.Iterator接口:不提供存储对象的能力,主要用于遍历Collection中的元素
二、Iterator(迭代器)接口
1.常用方法
2.foreach循环
三、Collection接口及方法
1.添加方法
2.判断方法
3.删除方法
4.其他方法
四、 Collection子接口1:List
1.List接口特点
2.List接口方法
3.List接口主要实现类之一:ArrayList
4.List的实现类之二:LinkedList
5.List的实现类之三:Vector
五、Collection子接口2:Set
详解(如果你有疑问,可跳转到另一篇文章查看)
1.Set接口概述
2.Set主要实现类:HashSet
HashSet概述:
方法:
示例:
3.Set主要实现类二:LinkedHashSet
与HashSet相比,LinkedHashSet有以下特点:
4.Set实现类之三:TreeSet
1.TreeSet概述
常用方法:
六、总结
List接口的实现类特点:
Set接口的实现类特点:
下一篇:Map接口及子实现类,Collections工具类
一、Java 集合框架体系
1.Collection接口:用于存储一个一个的数据,也称单列数据集合(single)
。
-
List子接口:用来存储有序的、可以重复的数据(主要用来替换数组,"动态"数组)
-
实现类:ArrayList(主要实现类)、LinkedList、Vector
-
-
Set子接口:用来存储无序的、不可重复的数据(类似于高中讲的"集合")
-
实现类:HashSet(主要实现类)、LinkedHashSet、TreeSet
-
2.Map接口:用于存储具有映射关系“key-value对”的集合(couple)
-
HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties
3.Iterator
接口:不提供存储对象的能力,主要用于遍历
Collection中的元素
二、Iterator(迭代器)接口
1.常用方法
方法 | 描述 |
---|---|
public Iterator iterator() | 获取集合对应的迭代器,用来遍历集合中的元素 |
public E next() | 返回迭代的下一个元素 |
public boolean hasNext() | 如果仍有元素可以迭代,则返回 true |
void remove() | 从集合中删除迭代器返回的最后一个元素(可选操作) |
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
Iterator<String> iterator = list.iterator(); // 获取迭代器
while(iterator.hasNext()) {
String element = iterator.next(); // 获取下一个元素
System.out.println(element);
}
输出:
apple
banana
orange
2.foreach循环
-
foreach循环的语法格式:
for(元素的数据类型 局部变量 : Collection集合或数组){
//操作局部变量的输出操作
}
//这里局部变量就是一个临时变量,自己命名就可以
-
对于集合的遍历,增强for的内部原理其实是个Iterator迭代器。如下图。
当编译器遇到增强for循环时,会自动生成一个与该集合对应的迭代器,并使用迭代器来迭代集合中的元素。在每次循环中,编译器会自动调用迭代器的next()
方法获取下一个元素,并将其赋值给element
变量。当集合中没有更多元素时,迭代器的hasNext()
方法会返回false
,循环结束。
- 它用于遍历Collection和数组。通常只进行遍历元素,不能在遍历的过程中对集合元素进行增删操作。
public class Test {
public static void main(String[] args) {
String[] str ={"aa","bb", "cc", "dd", "ee"};
for (String myStr : str) {
myStr = "wrong";
System.out.println(myStr);
}
for (int i = 0; i < str.length; i++) {
System.out.println(str[i]);
}
}
}
wrong
wrong
wrong
wrong
wrong
aa
bb
cc
dd
ee
三、Collection接口及方法
1.添加方法
add(E obj) | 添加元素对象到当前集合中 |
addAll(Collection other) | 添加other集合中的所有元素对象到当前集合中,即this = this ∪ other |
public class Test {
public static void main(String[] args) {
testAdd();
testAddAll();
}
public static void testAdd(){
//ArrayList是Collection的子接口List的实现类之一。
//因为Collection是一个接口,而不是一个具体的类,不能直接被实例化。在Java中,接口是一种抽象类型,只定义了接口的方法声明,而没有具体的实现。
//因此,我们不能通过"new Collection()"来创建一个Collection对象。
//相反,ArrayList是Collection接口的一个具体实现类,它提供了对一个动态大小的数组的操作方法。
//所以,我们可以使用"new ArrayList()"来创建一个ArrayList对象,并将其赋值给Collection类型的变量coll。
//可以根据需要选择不同的类作为接口的实现类,因为接口可以有多个实现类
Collection coll = new ArrayList();
coll.add("486");
coll.add("艾米莉亚");
coll.add("蕾姆");
System.out.println(coll);
}
public static void testAddAll(){
Collection c1 = new ArrayList();
c1.add(1);
c1.add(2);
System.out.println("c1集合元素的个数:" + c1.size());//2
System.out.println("c1 = " + c1);
Collection c2 = new ArrayList();
c2.add(1);
c2.add(2);
System.out.println("c2集合元素的个数:" + c2.size());//2
System.out.println("c2 = " + c2);
Collection other = new ArrayList();
other.add(1);
other.add(2);
other.add(3);
System.out.println("other集合元素的个数:" + other.size());//3
System.out.println("other = " + other);
System.out.println();
c1.addAll(other);
System.out.println("c1集合元素的个数:" + c1.size());//5
System.out.println("c1.addAll(other) = " + c1);
c2.add(other);
System.out.println("c2集合元素的个数:" + c2.size());//3
System.out.println("c2.add(other) = " + c2);
}
}
输出:
[486, 艾米莉亚, 蕾姆]
c1集合元素的个数:2
c1 = [1, 2]
c2集合元素的个数:2
c2 = [1, 2]
other集合元素的个数:3
other = [1, 2, 3]c1集合元素的个数:5
c1.addAll(other) = [1, 2, 1, 2, 3]
c2集合元素的个数:3
c2.add(other) = [1, 2, [1, 2, 3]]
2.判断方法
方法名 | 方法描述 |
---|---|
int size() | 获取当前集合中实际存储的元素个数 |
boolean isEmpty() | 判断当前集合是否为空集合 |
boolean contains(Object obj) | 判断当前集合中是否存在一个与obj对象equals返回true的元素 |
boolean containsAll(Collection coll) | 判断coll集合中的元素是否在当前集合中都存在。即coll集合是否是当前集合的“子集” |
boolean equals(Object obj) | 判断当前集合与obj是否相等 |
区分: contains与 containsAll
public class Test {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add(1);
c1.add(2);
System.out.println("c1集合元素的个数:" + c1.size());//2
System.out.println("c1 = " + c1);
Collection c2 = new ArrayList();
c2.add(1);
c2.add(2);
System.out.println("c2集合元素的个数:" + c2.size());//2
System.out.println("c2 = " + c2);
Collection other = new ArrayList();
other.add(1);
other.add(2);
other.add(3);
System.out.println("other集合元素的个数:" + other.size());//3
System.out.println("other = " + other);
System.out.println();
c1.addAll(other);
System.out.println("c1集合元素的个数:" + c1.size());//5
System.out.println("c1.addAll(other) = " + c1);
System.out.println("c1.contains(other) = " + c1.contains(other));
System.out.println("c1.containsAll(other) = " + c1.containsAll(other));
System.out.println();
c2.add(other);
System.out.println("c2集合元素的个数:" + c2.size());
System.out.println("c2.add(other) = " + c2);
System.out.println("c2.contains(other) = " + c2.contains(other));
System.out.println("c2.containsAll(other) = " + c2.containsAll(other));
}
}
输出:
c1集合元素的个数:2
c1 = [1, 2]
c2集合元素的个数:2
c2 = [1, 2]
other集合元素的个数:3
other = [1, 2, 3]c1集合元素的个数:5
c1.addAll(other) = [1, 2, 1, 2, 3]
c1.contains(other) = false
c1.containsAll(other) = truec2集合元素的个数:3
c2.add(other) = [1, 2, [1, 2, 3]]
c2.contains(other) = true
c2.containsAll(other) = false
3.删除方法
方法 | 描述 |
---|---|
void clear() | 清空集合元素 |
boolean remove(Object obj) | 从当前集合中删除第一个找到的与obj对象equals返回true的元素。 |
boolean removeAll(Collection coll) | 从当前集合中删除所有与coll集合中相同的元素。即this = this - this ∩ coll |
boolean retainAll(Collection coll) | 从当前集合中删除两个集合中不同的元素,使得当前集合仅保留与coll集合中的元素相同的元素,即当前集合中仅保留两个集合的交集,即this = this ∩ coll; |
区别 :removeAll和retainAll
public class Test {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("486");
coll.add("艾米莉亚");
coll.add("蕾姆");
coll.add("拉姆");
System.out.println("coll = " + coll);
Collection other = new ArrayList();
other.add("艾米莉亚");
other.add("蕾姆");
other.add("拉姆");
System.out.println("other = " + other);
coll.retainAll(other);
System.out.println("coll.retainAll(other)之后,coll = " + coll);
System.out.println("coll.retainAll(other)之后,other = " + other);
System.out.println();
Collection coll1 = new ArrayList();
coll1.add("486");
coll1.add("艾米莉亚");
coll1.add("蕾姆");
coll1.add("拉姆");
System.out.println("coll1 = " + coll1);
Collection other1 = new ArrayList();
other1.add("艾米莉亚");
other1.add("蕾姆");
other1.add("拉姆");
System.out.println("other1 = " + other1);
coll1.removeAll(other1);
System.out.println("coll1.removeAll(other1)之后,coll1 = " + coll1);
System.out.println("coll1.removeAll(other1)之后,other1 = " + other1);
}
}
输出:
coll = [486, 艾米莉亚, 蕾姆, 拉姆]
other = [艾米莉亚, 蕾姆, 拉姆]
coll.retainAll(other)之后,coll = [艾米莉亚, 蕾姆, 拉姆]
coll.retainAll(other)之后,other = [艾米莉亚, 蕾姆, 拉姆]coll1 = [486, 艾米莉亚, 蕾姆, 拉姆]
other1 = [艾米莉亚, 蕾姆, 拉姆]
coll1.removeAll(other1)之后,coll1 = [486]
coll1.removeAll(other1)之后,other1 = [艾米莉亚, 蕾姆, 拉姆]
4.其他方法
方法名 | 功能描述 |
---|---|
toArray() | 返回包含当前集合中的一个Object[] 类型的数组(集合转数组) |
toArray(T[] a) | 将集合转换为指定类型的数组,并将集合元素存储到指定的数组中。 |
asList() | 数组转集合 |
hashCode() | 获取集合对象的哈希值 |
iterator() | 返回迭代器对象,用于集合遍历 |
public class Test {
public static void main(String[] args) {
System.out.println("集合转数组遍历1:");
Collection<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
Object[] str = list.toArray();
for (Object s: str
) {
System.out.println(s);
}
System.out.println("集合转数组遍历2:");
String[] str2 = new String[list.size()];
String[] array = list.toArray(str2);
for (String s: array) {
System.out.println(s);
}
System.out.println("数组转集合迭代器遍历:");
String[] str1 = {"dd","ee","ff"};
Collection<String> list1 = Arrays.asList(str1);
Iterator<String> iterator = list1.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
集合转数组遍历1:
aaa
bbb
ccc
集合转数组遍历2:
aaa
bbb
ccc
数组转集合迭代器遍历:
dd
ee
ff
四、 Collection子接口1:List
1.List接口特点
-
鉴于Java中数组用来存储数据的局限性,我们通常使用
java.util.List
替代数组 -
List集合类中
元素有序
、且可重复
,集合中的每个元素都有其对应的顺序索引(从0开始)。
2.List接口方法
功能 | 方法 | 描述 |
---|---|---|
插入元素 | void add(int index, Object ele) | 在index位置插入ele元素 |
boolean addAll(int index, Collection eles) | 从index位置开始将eles中的所有元素添加进来 | |
获取元素 | Object get(int index) | 获取指定index位置的元素 |
List subList(int fromIndex, int toIndex) | 返回从fromIndex到toIndex位置的子集合 | |
获取元素索引 | int indexOf(Object obj) | 返回obj在集合中首次出现的位置 |
int lastIndexOf(Object obj) | 返回obj在当前集合中末次出现的位置 | |
删除和替换元素 | Object remove(int index) | 移除指定index位置的元素,并返回此元素 |
Object set(int index, Object ele) | 设置指定index位置的元素为ele |
3.List接口主要实现类之一:ArrayList
-
ArrayList 是 List 接口的
主要实现类
-
本质上,ArrayList是对象引用的一个”变长”数组,允许重复和空元素
-
当添加或删除元素时,
ArrayList
会自动调整数组的大小以容纳新的元素或释放对应的空间。 -
Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是 Vector 实例。 Arrays.asList(…) 返回值是一个固定长度的 List 集合
ArrayList方法:ArrayList (Java SE 11 & JDK 11 ) (runoob.com)
4.List的实现类之二:LinkedList
-
实现了
List
接口和Deque
接口,对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高。这是由底层采用链表(双向链表)结构存储数据决定的。 - LinkedList方法:LinkedList (Java SE 11 & JDK 11 ) (runoob.com)
特有方法:
方法名 | 功能描述 | 返回值类型 |
---|---|---|
addFirst(Object obj) | 将指定的元素作为列表的第一个元素插入。如果列表为空,则该元素也将成为最后一个元素。 | void |
addLast(Object obj) | 将指定的元素作为列表的最后一个元素插入。如果列表为空,则该元素也将成为第一个元素。 | void |
getFirst() | 返回列表中的第一个元素,但不会移除它。 | Object |
getLast() | 返回列表中的最后一个元素,但不会移除它。 | Object |
removeFirst() | 移除并返回列表中的第一个元素。 | Object |
removeLast() | 移除并返回列表中的最后一个元素。 | Object |
5.List的实现类之三:Vector
-
Vector 是一个
古老
的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全
的。 -
在各种List中,最好把
ArrayList作为默认选择
。当插入、删除频繁时,使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。 -
特有方法:
方法名称 | 方法描述 |
---|---|
addElement(Object obj) | 将指定的元素添加到此向量的末尾。 |
insertElementAt(Object obj, int index) | 在指定的索引处插入指定的元素。原来在该位置和所有后续元素上的元素都向右移动。 |
setElementAt(Object obj, int index) | 将指定索引处的元素设置为指定的对象。 |
removeElement(Object obj) | 从向量中移除指定的元素。如果存在多个匹配的元素,则只移除第一个匹配的元素。 |
removeAllElements() | 从向量中移除所有元素。 |
五、Collection子接口2:Set
1.Set接口概述
-
Set接口是Collection的子接口,Set接口相较于Collection接口没有提供额外的方法
-
Set 集合不允许包含相同的Value,如果试把两个相同的Value加入同一个 Set 集合中,则添加操作失败。因为Set集合是基于哈希表的一种数据结构,在插入元素时会根据元素的哈希值进行判断和处理,确保集合中没有重复的元素。
-
Set集合支持的遍历方式和Collection集合一样:foreach和Iterator。
-
Set的常用实现类有:HashSet、TreeSet、LinkedHashSet。
2.Set主要实现类:HashSet
详解(如果你想了解更多,可跳转到另一篇文章查看)
HashSet概述:
-
无序性:HashSet中的元素是无序的,不会按照插入的顺序进行存储和访问。
-
不可重复性:HashSet中的元素是唯一的,不会存在重复的元素。这是通过哈希表的机制来实现的。
-
允许存储null值:HashSet允许存储一个null元素。
-
内部实现机制:HashSet基于哈希表实现,使用了哈希函数来计算元素的存储位置,所以HashSet集合中元素的无序性,不等同于随机性。这里的无序性与元素的添加位置有关。具体来说:我们在添加每一个元素到数组中时,具体的存储位置是由元素的hashCode()调用后返回的hash值决定的。导致在数组中每个元素不是依次紧密存放的,表现出一定的无序性。
-
HashSet 集合
判断两个元素相等的标准
:两个对象通过hashCode()
方法得到的哈希值相等,并且两个对象的equals()
方法返回值为true。 -
对于存放在Set容器中的对象,对应的类一定要重写hashCode()和equals(Object obj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
-
HashSet集合中元素的无序性,不等同于随机性。这里的无序性与元素的添加位置有关。具体来说:我们在添加每一个元素到数组中时,具体的存储位置是由元素的hashCode()调用后返回的hash值决定的。导致在数组中每个元素不是依次紧密存放的,表现出一定的无序性。
HashSet方法:HashSet (Java SE 11 & JDK 11 ) (runoob.com)
方法:
方法 | 描述 |
---|---|
boolean add(E e) | 如果指定的元素尚不存在,则将其添加到此集合中。 |
void clear() | 从该集中删除所有元素。 |
boolean contains(Object o) | 如果此 set 包含指定的元素,则返回 true。 |
boolean isEmpty() | 如果此集合不包含任何元素,则返回 true。 |
Iterator<E> iterator() | 返回此 set 中元素的迭代器。 |
boolean remove(Object o) | 如果存在,则从该集合中移除指定的元素。 |
int size() | 返回此集合中的元素数(基数)。 |
示例:
去除重复数字值:
public static List duplicateList(List a) {
HashSet set = new HashSet();
set.addAll(a);
return new ArrayList(set);
}
public static void main(String[] args) {
Integer[] array = {1, 1, 3, 4, 4};
// 将数组转换为集合
List<Integer> list = Arrays.asList(array);
//list转为set达到去重的效果
List list2 = duplicateList(list);
for (Object integer : list2) {
System.out.println(integer);
}
}
3.Set主要实现类二:LinkedHashSet
LinkedHashSet是Java集合框架中的一种集合实现,它继承自HashSet类,它根据元素的 hashCode 值来决定元素的存储位置,同时使用一个双向链表维护元素的插入顺序。
与HashSet相比,LinkedHashSet有以下特点:
-
保持插入顺序:LinkedHashSet保持了元素的插入顺序。当我们向LinkedHashSet中添加元素时,它们会按照添加的顺序被保存,并且在遍历时按照相同的顺序返回。这使得LinkedHashSet非常适合于需要按照元素的插入顺序进行遍历或组织的场景。
-
高效的查找操作:与HashSet一样,LinkedHashSet使用哈希表实现元素的存储,因此查找元素的效率很高。在大多数查找操作中,LinkedHashSet的性能与HashSet相当。
-
相对较高的存储开销:由于LinkedHashSet需要维护元素插入顺序,它需要额外的存储空间来维护链表。因此,相对于HashSet,LinkedHashSet在存储方面稍微占用更多的内存。
public class Test {
public static void main(String[] args) {
LinkedHashSet set = new LinkedHashSet<>();
// 添加元素
set.add("apple");
set.add(1);
set.add(2);
set.add('e');
set.add(0.14159);
// 遍历集合
for (Object element : set) {
System.out.println(element);
}
// 判断元素是否存在
boolean contains = set.contains(2 );
System.out.println("Contains '2': " + contains);
// 移除元素
boolean removed = set.remove(1);
System.out.println("Removed '1': " + removed);
//按添加时的顺序输出
System.out.println(set);
}
}
输出:
apple
1
2
e
0.14159
Contains '2': true
Removed '1': true
[apple, 2, e, 0.14159]
4.Set实现类之三:TreeSet
1.TreeSet概述
-
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以按照添加的元素的指定的属性的大小顺序进行遍历。
-
TreeSet底层使用
红黑树
结构存储数据 -
TreeSet特点:不允许重复、实现排序(自然排序或定制排序)
-
TreeSet 两种排序方法:
自然排序
和定制排序
。默认情况下,TreeSet 采用自然排序。-
自然排序
:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。-
如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
-
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
-
-
定制排序
:如果元素所属的类没有实现Comparable接口,或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序,则考虑使用定制排序。定制排序,通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。-
利用int compare(T o1,T o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
-
要实现定制排序,需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。
-
-
-
因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是
同一个类的对象
。
常用方法:
方法 | 描述 |
---|---|
add(E e) | 向TreeSet中添加指定的元素。 |
addAll(Collection<? extends E> c) | 将指定集合中的所有元素添加到TreeSet中。 |
clear() | 从TreeSet中移除所有元素。 |
contains(Object o) | 检查TreeSet中是否包含指定的元素。 |
first() | 返回TreeSet中的第一个(最小)元素。 |
last() | 返回TreeSet中的最后一个(最大)元素。 |
isEmpty() | 检查TreeSet是否为空。 |
remove(Object o) | 从TreeSet中移除指定的元素。 |
size() | 返回TreeSet中的元素数量。 |
iterator() | 返回在TreeSet中元素上进行迭代的迭代器。 |
subSet(E fromElement, E toElement) | 返回一个子集,包括从fromElement(包括)到toElement(不包括)的所有元素。 |
headSet(E toElement) | 返回一个子集,包括小于toElement的所有元素。 |
tailSet(E fromElement) | 返回一个子集,包括大于等于fromElement的所有元素。 |
ceiling(E e) | 返回TreeSet中大于或等于给定元素e的最小元素。 |
floor(E e) | 返回TreeSet中小于或等于给定元素e的最大元素。 |
示例:创建了一个自定义的比较器AgeComparator
,它比较Student对象的年龄属性。然后将该比较器传递给TreeSet的构造函数,使得集合按照学生的年龄进行排序。
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetObjectPropertyOrderingExample {
public static void main(String[] args) {
TreeSet<Student> set = new TreeSet<>(new AgeComparator());
// 添加学生对象
set.add(new Student("Alice", 20));
set.add(new Student("Bob", 18));
set.add(new Student("Charlie", 22));
// 遍历集合(按照年龄排序)
for (Student student : set) {
System.out.println(student.getName() + " : " + student.getAge());
}
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
return Integer.compare(s1.getAge(), s2.getAge());
}
}
其中:
(new LengthComparator())
是创建一个比较器的实例,并将其作为参数传递给构造函数的简写方式,允许在创建TreeSet时即刻创建并传递一个比较器。
如果你更容易理解完整的步骤,可以按照下面的方式进行:
- 首先,你需要创建一个实现了
Comparator
接口的类,该接口指定了比较器的行为。
class LengthComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
//如果s1.length()小于s2.length(),则返回负整数值。
//如果s1.length()等于s2.length(),则返回0。
//如果s1.length()大于s2.length(),则返回正整数值。
}
}
- 接下来,你可以实例化比较器的对象:
Comparator<String> lengthComparator = new LengthComparator();
- 然后,你可以使用该比较器对象创建TreeSet对象,并传递比较器对象作为参数:
TreeSet<String> set = new TreeSet<>(lengthComparator);
综合以上三步,你可以用下面的代码来替代 (new LengthComparator())
这样的写法:
Comparator<String> lengthComparator = new LengthComparator();
TreeSet<String> set = new TreeSet<>(lengthComparator);
这样更详细的写法可能更容易理解,但是对于简单的比较器,可以直接在构造函数中使用new 比较器类名()
的方式来创建并传递比较器对象。
输出:
Bob : 18
Alice : 20
Charlie : 22
六、总结
List接口的实现类特点:
- ArrayList:基于数组实现,支持随机访问和快速的插入/删除操作。适用于频繁访问元素和对元素进行插入和删除的场景,但不适用于频繁的插入和删除操作。
- LinkedList:基于链表实现,支持高效的插入/删除操作和快速的查找操作。适用于频繁插入和删除元素的场景,但访问元素性能相对较低。
LinkedList
还实现了Deque
接口,它提供了一系列特殊的链表操作,例如添加/删除首尾元素、获取首尾元素等。 - Vector:与ArrayList类似,但是是线程安全的(采用同步机制)。
ArrayList
和LinkedList
是不安全的,这意味着它们在多线程环境下不能保证线程安全。如果多个线程同时修改一个ArrayList
或LinkedList
实例,可能会导致数据不一致或出现并发访问异常。因此,在多线程环境下使用时,需要使用额外的同步机制来保证线程安全,例如使用Collections.synchronizedList
等方法或使用并发集合类CopyOnWriteArrayList
等。
Vector
是线程安全的,它对其方法进行了同步化,以保证多线程环境下的安全访问。这意味着多个线程可以安全地同时修改一个Vector
实例,而不会导致数据不一致或出现并发访问异常。然而,这种同步化会带来额外的开销,可能导致在性能上略有劣势。
在Java 1.2版本之后,引入了更高效的并发集合类,如ConcurrentHashMap
、ConcurrentLinkedDeque
和CopyOnWriteArrayList
,它们提供了更好的线程安全性和性能。因此,在现代的Java应用程序中,通常建议使用这些并发集合类来替代Vector
、ArrayList
和LinkedList
。
Set接口的实现类特点:
- 它们在多线程环境下都不能保证线程安全
- HashSet:基于哈希表实现,不保证元素的顺序,并且不可重复。查找元素速度快,但无法保持元素的顺序。
- LinkedHashSet:基于链表和哈希表实现,使用一个双向链表维护元素的插入顺序。相比HashSet,插入和删除操作稍慢一些,但仍然较快。
- TreeSet:基于红黑树实现,能够保持元素的有序性。插入和删除操作的性能较慢,但查找元素和按序访问元素的性能非常高。
List接口提供了有序的、可重复的集合,适用于需要保持元素插入顺序或允许重复元素的场景。Set接口提供了无序的、不可重复的集合,适用于需要确保元素唯一性和不关心元素顺序的场景。
需要根据实际需求选择合适的List和Set实现类。如果需要频繁插入和删除元素,可以选择LinkedList和HashSet。如果需要高效的随机访问和根据元素顺序迭代,可以选择ArrayList和LinkedHashSet。如果需要有序集合,可以选择TreeSet或LinkedHashSet。
方法总结:
List接口方法
功能 | 方法 | 描述 |
---|---|---|
插入元素 | void add(int index, Object ele) | 在index位置插入ele元素 |
boolean addAll(int index, Collection eles) | 从index位置开始将eles中的所有元素添加进来 | |
获取元素 | Object get(int index) | 获取指定index位置的元素 |
List subList(int fromIndex, int toIndex) | 返回从fromIndex到toIndex位置的子集合 | |
获取元素索引 | int indexOf(Object obj) | 返回obj在集合中首次出现的位置 |
int lastIndexOf(Object obj) | 返回obj在当前集合中末次出现的位置 | |
删除和替换元素 | Object remove(int index) | 移除指定index位置的元素,并返回此元素 |
Object set(int index, Object ele) | 设置指定index位置的元素为ele |
LinkedList实现类方法:
Vector实现类方法:
HashSet实现类方法:
方法 | 描述 |
---|---|
boolean add(E e) | 如果指定的元素尚不存在,则将其添加到此集合中。 |
void clear() | 从该集中删除所有元素。 |
boolean contains(Object o) | 如果此 set 包含指定的元素,则返回 true。 |
boolean isEmpty() | 如果此集合不包含任何元素,则返回 true。 |
Iterator<E> iterator() | 返回此 set 中元素的迭代器。 |
boolean remove(Object o) | 如果存在,则从该集合中移除指定的元素。 |
int size() | 返回此集合中的元素数(基数)。 |
Tree实现类方法
方法 | 描述 |
---|---|
add(E e) | 向TreeSet中添加指定的元素。 |
addAll(Collection<? extends E> c) | 将指定集合中的所有元素添加到TreeSet中。 |
clear() | 从TreeSet中移除所有元素。 |
contains(Object o) | 检查TreeSet中是否包含指定的元素。 |
first() | 返回TreeSet中的第一个(最小)元素。 |
last() | 返回TreeSet中的最后一个(最大)元素。 |
isEmpty() | 检查TreeSet是否为空。 |
remove(Object o) | 从TreeSet中移除指定的元素。 |
size() | 返回TreeSet中的元素数量。 |
iterator() | 返回在TreeSet中元素上进行迭代的迭代器。 |
subSet(E fromElement, E toElement) | 返回一个子集,包括从fromElement(包括)到toElement(不包括)的所有元素。 |
headSet(E toElement) | 返回一个子集,包括小于toElement的所有元素。 |
tailSet(E fromElement) | 返回一个子集,包括大于等于fromElement的所有元素。 |
ceiling(E e) | 返回TreeSet中大于或等于给定元素e的最小元素。 |
floor(E e) | 返回TreeSet中小于或等于给定元素e的最大元素。 |