概述
- Collection:存储一组不唯一,无序的对象
- List:存储一组不唯一,有序(插入顺序)的对象
- 访问集合中的元素可以根据元素的索引来访问。
- Set:存储一组唯一,无序的对象
- 访问集合中的元素只能根据元素本身来访问(也是集合里元素不允许重复的原因)。
- SortedSet是一个按照升序排列元素的Set。
- Map:存储一组键值对象,提供key到value的映射
- 访问时只能根据每项元素的 key 来访问其 value。
- SortedMap是一个按照升序排列
- key的Map
集合框架分为以下几个部分
- 数据结构:List列表、Queue队列、Deque双端队列、Set集合、Map映射
- 比较器:Comparator比较器和Comparable排序接口
- 算法:Collections常用算法类、Arrays静态数组的排序、查找算法
- 迭代器:Iterator通用迭代器、ListIterator针对 List 特化的迭代器
集合类的工具类:Collections类和Arrays类
- Arrays:操作数组,提供搜索、排序、复制等静态方法。
public static void main(String[] args) {
int[] array = new int[]{11, 4, 23, 16, 3, 1, 4};
Arrays.sort(array);
System.out.println(Arrays.toString(array));//[1, 3, 4, 4, 11, 16, 23]
}
- Collections:操作集合,提供搜索、排序、线程安全化等操作。
Collection是集合的父类接口,Collections类是集合的工具类;
public static void main(String[] args) {
List list = new ArrayList();
list.add(17);
list.add(11);
list.add(65);
list.add(36);
Collections.sort(list);
System.out.println(list);//[11, 17, 36, 65]
}
Comparable和Comparator接口
Comparable和Comparator都是java的接口,Comparable在java.lang包下,而Comparator在java.util包下,两者功能都是排序。
Comparable 接口
- 只要一个类实现了这个接口就可以意味着这个类支持排序。
- 实现了这个类的接口的列表或者数组可以可以使用Collections.sort或Arrays.sort进行排序。
- 该接口的定义
public interface Comparable<T>{
public int compareTo(T o); // 只用compareTo方法,实现这个接口的类必须要重写这个方法
}
- 比较的规则
- 如果该对象和指定比较的对象相等,那么返回0。
- 如果该对象比指定比较的对象大,那么返回正数。
- 如果该对象比指定比较的对象小,返回负数。
class Person implements Comparable<Person>{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person person) {
return this.age - person.age;
}
}
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
Person[] persons = new Person[]{new Person("tom", 20), new Person("jack", 12)};
System.out.print("排序之前:");
for (Person p : persons) {
System.out.print("name:" + p.name + ", age:" + p.age + " ");
}
// 排序之后
Arrays.sort(persons);
System.out.println("排序之后:");
for (Person p : persons) {
System.out.print("name:" + p.name + ", age:" + p.age + " ");
}
}
Comparator 接口
- 如果我们想要控制某个类的次序,而这个类并没有继承Comparable接口,那么我们就可以使用Comparator接口; 因此可以说,Comparator接口是Comparable接口的挽救接口。
- 比较的规则:大致和上面的规则相同,但也有不同的地方。
Collection 接口
Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List
Set 接口
- 添加到Set中的元素必须定义
equals方法,以提供算法来判断欲添加进来的对象是否与已经存在的某对象相等,从而建立对象的唯一性。 - 实现Set接口的类有HashSet,TreeSet
public class SetDemo{
public static void main(String[] argv){
HashSer<String> h = new HashSet<String>();
// 也可以 Set h = new HashSet()
h.add("one");
h.add("Two");
h.add("one"); // DUPLICATE
h.add("Three");
Iterator<String> it = h.iterator();
while(it.hasNext()){
System.ou.println(it.next());
}
}
}
Three
One
Two
List 接口
- 实现它的类有ArrayList和LinkedList。
- ArrayList
- 顺序存储
- 长度可变
- 遍历元素和随机访问元素的效率比较高
- LinkedList
- 链表
- 插入、删除元素时效率比较高
- ArrayList
ArrayList
boolean add(Object o):在列表的末尾顺序添加元素,起始索引位置从0开始void add(int index, Object o):在指定的索引位置添加元素。索引位置必须介于0和列表中元素个数之间int size():返回列表中的元素个数Object get(int index):返回指定索引位置处的元素。取出的元素是Object类型,使用前需要进行强制类型转换boolean contains(Object o):判断列表中是否存在指定元素boolean remove(Object o):从列表中删除指定元素Object remove(int index):从列表中删除指定位置元素,起始索引位置从0开始
LinkedList
void addFirst(Object o):在列表的首部添加元素void addLast(Object o):在列表的末尾添加元素Object getFirst():返回列表中的第一个元素Object getLast():返回列表中的最后一个元素Object removeFirst():删除并返回列表中的第一个元素Object removeLast():删除并返回列表中的最后一个元素
Map接口
-
最常用的实现类是HashMap
-
Object put(Object key, Object val):以“键-值对”的方式进行存储 -
Object get (Object key):根据键返回相关联的值,如果不存在指定的键,返回null -
Object remove (Object key):删除由指定的键映射的“键-值对” -
int size():返回元素个数 -
Set keySet ():返回键的集合 -
Collection values ():返回值的集合 -
Boolean containsKey (Object key):如果存在由指定的键映射的“键-值对”,返回true
集合类对比
-
Vector和ArrayList的异同
- 实现原理相同,功能相同,很多情况下可以互用
- 两者的主要区别如下
- Vector线程安全,ArrayList重速度轻安全,线程非安全
- 长度需增长时,Vector默认增长一倍,ArrayList增长50%
-
Hashtable和HashMap的异同
- 实现原理相同,功能相同,在很多情况下可以互用
- 两者的主要区别如下
- Hashtable继承Dictionary类,HashMap实现Map接口
- Hashtable线程安全,HashMap线程非安全
- Hashtable不允许null值,HashMap允许null值
迭代器Iteraor——用于遍历集合
- 所有集合接口和类都没有提供相应遍历方法,而是由Iterator实现集合遍历
- Collection 接口的iterate()方法返回一个Iterator,然后通过Iterator接口的两个方法可实现遍历
boolean hasNext(): 判断是否存在另一个可访问的元素Object next(): 返回要访问的下一个元素
泛型
泛型类和接口
泛型类和接口允许定义一个或多个类型参数。这些参数在类或接口被实例化时指定,用于指定类或接口中使用的具体类型。
// 泛型类
public class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
// 泛型接口
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
// 实现泛型接口
public class StringIntegerPair implements Pair<String, Integer> {
private String key;
private Integer value;
public StringIntegerPair(String key, Integer value) {
this.key = key;
this.value = value;
}
@Override
public String getKey() {
return key;
}
@Override
public Integer getValue() {
return value;
}
}
// 使用泛型接口
public class Main {
public static void main(String[] args) {
Pair<String, Integer> pair = new StringIntegerPair("Key", 123);
System.out.println("Key: " + pair.getKey() + ", Value: " + pair.getValue());
}
}
泛型方法
泛型方法可以定义在普通类或泛型类中,方法参数和返回值可以是泛型类型。
public class Util {
// 泛型方法
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
public class Util {
// 泛型方法
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}
}
// 使用泛型方法
public class Main {
public static void main(String[] args) {
String[] stringArray = {"Hello", "Generics", "Java"};
Util.printArray(stringArray);
Integer[] integerArray = {1, 2, 3, 4, 5};
Util.printArray(integerArray);
}
}
类型参数命名约定
E- 元素(Element),例如在集合中使用。K- 键(Key),例如在映射中使用。V- 值(Value),例如在映射中使用。T- 类型(Type),通用类型。U,V,W等 - 第二个、第三个、第四个类型。
通配符类型
通配符类型用于表示未知的类型。主要有三种形式:
?- 无界通配符,表示未知类型。
public class Util {
// 使用通配符类型的方法
public static void printCollection(Collection<?> collection) {
// 使用通配符类型 ?,意味着它可以接受任何类型的 Collection。
// 这使得方法更加通用,可以接受不同类型的 Collection 实例。
for (Object element : collection) {
System.out.println(element);
}
}
}
// 使用通配符类型的方法
public class Main {
public static void main(String[] args) {
Collection<String> stringCollection = Arrays.asList("Hello", "Generics", "Java");
Util.printCollection(stringCollection);
Collection<Integer> integerCollection = Arrays.asList(1, 2, 3, 4, 5);
Util.printCollection(integerCollection);
}
}
? extends T- 上界通配符,表示上界为T的类型。
public void processNumbers(List<? extends Number> list) {
// ...
}
// processNumbers 方法可以接受任何 Number 类型的子类型的 List,如 Integer、Double 等。
? super T- 下界通配符,表示下界为T的类型。
public void addNumbers(List<? super Integer> list) {
// ...
}
// addNumbers 方法可以接受任何 Integer 类型的父类型的 List,如 Number、Object 等。
泛型的限制
- 不能使用基本类型作为泛型参数。
- 不能创建泛型数组。
- 不能实例化泛型类型。
- 不能在静态上下文中使用类型参数。
泛型的优点
- 提高类型安全性:编译时检查类型,减少运行时错误。
- 提高代码可重用性:无需为每种类型编写不同的代码。
- 提高代码可读性:通过类型参数明确指出类、接口或方法操作的数据类型。






