目录
一:集合的体系
Java中的集合体系结构是一个为表示和操作集合而设计的统一标准的体系结构,它主要由两大接口体系构成:Collection
接口体系和Map
接口体系。
Collection接口体系
Collection
接口是集合框架的根接口,用于表示一组元素的集合。它定义了集合的基本操作,如添加、删除、遍历等。Collection
接口体系主要包括以下几个子接口:
- List
- 特性:有序的集合,允许元素重复,有索引。
- 常用实现类:
ArrayList
:基于动态数组实现,适合随机访问。LinkedList
:基于链表实现,适合频繁的插入和删除操作。
- Set
- 特性:无序的集合,不允许元素重复,无索引。
- 常用实现类:
HashSet
:基于哈希表实现,不保证元素的顺序,效率较高。LinkedHashSet
:继承自HashSet
,通过链表维护元素的插入顺序。TreeSet
:基于红黑树实现,可以对元素进行排序。
Map接口体系
Map
接口用于存储键值对(key-value pairs),一个键可以映射到最多一个值。Map
接口体系主要包括以下几个实现类:
- HashMap
- 特性:基于哈希表的实现,提供快速的键查找能力。
- 注意:不保证映射的顺序,且允许一个键为
null
和多个值为null
。
- LinkedHashMap
- 特性:继承自
HashMap
,同时维护了一个双向链表来记录插入顺序或访问顺序。 - 注意:根据创建时指定的参数,可以维护插入顺序或访问顺序。
- 特性:继承自
- TreeMap
- 特性:基于红黑树实现,可以对键进行排序。
- 注意:自然排序或根据创建时提供的
Comparator
进行排序。
二:Collection集合
Collection的常见方法
Collection是单列集合的祖宗,它规定的方法是全部单列集合都会继承的。所以我们优先学习Collection的常见方法。
下面我将详细讲解Java中Collection
接口的一些常见方法,并通过代码示例来说明它们的使用。
方法名 | 说明 |
---|---|
boolean add(E e) | 把改定的对象添加到当前集合中 |
boolean addAll(Collection<? extends E> c) | 向集合中添加另一个集合的所有元素 |
void clear() | 移除集合中的所有元素 |
boolean contains(Object o) | 检查集合是否包含指定的元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
int size() | 返回集合中的元素数量 |
boolean isEmpty() | 检查集合是否为空 |
Object[] toArray() | 把集合中的元素存储到数组中 |
1. boolean add(E e)
向集合中添加一个元素。如果集合改变(即元素被添加),则返回true
。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>();
boolean result = collection.add("Hello");
System.out.println(result);
collection.add("小白杨");
System.out.println(collection);
输出:
true
[Hello, 小白杨]
}
}
2. boolean addAll(Collection<? extends E> c)
向集合中添加另一个集合的所有元素。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection1 = new ArrayList<>(Arrays.asList("Hello", "World"));
Collection<String> collection2 = new ArrayList<>(Arrays.asList("Java", "Programming"));
collection1.addAll(collection2);
System.out.println(collection1);
// 输出: [Hello, World, Java, Programming]
}
}
3. void clear()
移除集合中的所有元素。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));
collection.clear();
System.out.println(collection.isEmpty()); // 输出: true
}
}
4. boolean contains(Object o)
检查集合是否包含指定的元素。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));
boolean containsHello = collection.contains("Hello");
System.out.println("Contains 'Hello': " + containsHello);
// 输出: Contains 'Hello': true
boolean containsJava = collection.contains("Java");
System.out.println("Contains 'Java': " + containsJava);
// 输出: Contains 'Java': false
}
}
5. boolean remove(Object o)
从集合中移除指定的元素(如果存在)。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World"));
boolean removed = collection.remove("Hello");
System.out.println("Removed 'Hello': " + removed);
// 输出: Removed 'Hello': true
System.out.println(collection);
// 输出: [World]
}
}
6. int size()
返回集合中的元素数量。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World", "Java"));
int size = collection.size();
System.out.println("Size of the collection: " + size);
// 输出: Size of the collection: 3
}
}
7. boolean isEmpty()
检查集合是否为空。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>();
boolean isEmpty = collection.isEmpty();
System.out.println("Is the collection empty? " + isEmpty);
// 输出: Is the collection empty? true
collection.add("Hello");
isEmpty = collection.isEmpty();
System.out.println("Is the collection empty now? " + isEmpty);
// 输出: Is the collection empty now? false
}
}
8. Object[] toArray()
返回一个包含集合中所有元素的数组。返回的数组是对象类型,因此你可能需要类型转换来访问具体的元素。
import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>(Arrays.asList("Hello", "World", "Java"));
Object[] array = collection.toArray();
for (Object obj : array) {
System.out.println(obj); // 输出集合中的每个元素
}
// 如果你知道数组的类型,可以这样做:
String[] stringArray = collection.toArray(new String[0]);
for (String str : stringArray) {
System.out.println(str); // 同样输出集合中的每个元素,但避免了类型转换
}
}
}
迭代器
由于Collection
接口不直接支持通过索引访问元素(这是List
接口的特性),因此它提供了一种名为迭代器(Iterator)的机制来遍历集合中的元素。
迭代器是一个对象,它提供了一种统一的方法来遍历集合中的元素,而无需了解集合的内部结构。迭代器允许在遍历集合时移除元素,但不允许直接添加元素(尽管某些集合,如List
,提供了自己的方法来在迭代过程中添加元素,但这与迭代器本身无关)。
迭代器的基本方法
boolean hasNext()
:检查集合中是否还有元素未被遍历。E next()
:返回集合中下一个元素,并将迭代器的游标向前移动一位。如果集合中没有更多元素,则抛出NoSuchElementException
。void remove()
:从集合中移除通过next()
方法返回的最后一个元素(迭代器必须先调用next()
方法,才能调用remove()
方法,否则会抛出IllegalStateException
)。
代码解释
以下是一个使用迭代器遍历Collection
中元素的示例代码:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
// 创建一个Collection集合
Collection<String> collection = new ArrayList<>();
collection.add("Apple");
collection.add("Banana");
collection.add("Cherry");
// 获取迭代器
Iterator<String> iterator = collection.iterator();
// 使用迭代器遍历集合
while (iterator.hasNext()) {
// 迭代器移动到下一个元素,并返回当前(已移动前)的元素
String fruit = iterator.next();
System.out.println(fruit); // 打印当前元素
输出:
Apple
Banana
Cherry
//当读取到最后一个数据,迭代器移到下一个位置,此时已经没有元素了。hasNext返回的就是false。
}
// 注意:此时迭代器已经遍历完集合,再调用next()会抛出NoSuchElementException
}
}
增强for循环
①增强for可以用来遍历集合或者数组。
②增长for遍历集合,本质就是迭代器遍历集合的简化写法。
语法
对于数组:
for(类型 变量名 : 数组名) {
// 循环体
}
示例:
int[] numbers = {1, 2, 3, 4, 5};
for(int number : numbers) {
System.out.println(number);
}
对于集合(Collection
及其子接口如List
、Set
等):
for(类型 变量名 : 集合名) {
// 循环体
}
示例:
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
for(String fruit : fruits) {
System.out.println(fruit);
}
输出:
Apple
Banana
Cherry
注意事项
-
修改集合:虽然增强型for循环简化了遍历集合的过程,但它不直接支持在遍历过程中修改集合(如添加或删除元素)。如果需要在遍历过程中修改集合,应该考虑使用传统的for循环或迭代器,并通过迭代器的
remove()
方法来安全地删除元素。 -
类型推断:在增强型for循环中,变量
变量名
的类型是由数组或集合中元素的类型自动推断的,这得益于Java的类型推断机制(也称为“目标类型推断”)。 -
只读访问:由于增强型for循环不提供直接访问元素索引的方式,因此它主要用于对集合进行只读遍历。如果需要基于索引的访问,则应考虑使用传统的for循环或其他方法。
-
适用范围:增强型for循环特别适用于遍历数组和实现了
Iterable
接口的集合(如List
、Set
等)。对于没有实现Iterable
接口的集合(如Map
),则不能直接使用增强型for循环进行遍历,但可以通过entrySet()
、keySet()
或values()
方法将其转换为可迭代对象后再进行遍历。
使用 Consumer 和 Lambda 表达式遍历集合
由于Consumer<T>
是一个函数式接口,接口不能创建对象。所以你可以直接去new一个匿名内部类的对象出来。
import java.util.Arrays;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Cherry");
// 使用Lambda表达式遍历List
fruits.forEach(fruit -> System.out.println(fruit));
}
}
在没有Lambda表达式和默认方法之前,你可能需要这样遍历集合:
for (String fruit : fruits) {
System.out.println(fruit);
}
或者,使用迭代器:
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
但是,从Java 8开始,你可以使用 forEach
方法和Lambda表达式来更简洁地实现相同的功能:
fruits.forEach(new Consumer<String>() {
@Override
public void accept(String fruit) {
System.out.println(fruit);
}
});
然而,上面的写法仍然使用了匿名内部类。通过Lambda表达式,我们可