目录
2. 增强 for 循环(Enhanced for Loop)
3. 集合工具类(Collections Utility Class)
一、 List接口与实现类
理解列表接口(List Interface)以及其实现类,如 ArrayList、LinkedList 和 Vector,是 Java 编程中非常重要的一部分。列表是一种常见的数据结构,用于存储一组有序的元素,并提供了丰富的操作方法。下面是关于列表接口及其实现类的详细学习内容:
1. 列表接口(List Interface)
- 列表是一种有序的集合,允许元素重复,并且可以根据索引访问元素。
- Java 中的列表接口定义了一组操作列表的方法,包括添加、删除、获取元素、搜索元素等。
常用方法:
void add(E element)
:向列表末尾添加元素。void add(int index, E element)
:在指定位置插入元素。E get(int index)
:获取指定位置的元素。int size()
:返回列表中的元素数量。boolean isEmpty()
:判断列表是否为空。boolean contains(Object element)
:判断列表是否包含指定元素。int indexOf(Object element)
:返回指定元素第一次出现的索引。int lastIndexOf(Object element)
:返回指定元素最后一次出现的索引。E remove(int index)
:删除指定位置的元素。boolean remove(Object element)
:删除指定元素(如果存在)。void clear()
:清空列表中的所有元素。
2. ArrayList 类
ArrayList
是 Java 中常用的动态数组实现,它基于数组实现,可以动态扩展大小。- ArrayList 允许快速随机访问元素,但在插入和删除元素时性能略低于 LinkedList。
示例:
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
//添加元素
list.add("Apple");
list.add("Banana");
list.add("Orange");
System.out.println(list); // 输出: [Apple, Banana, Orange]
//获取元素数量
int size = list.size();//获取元素数量,为3
//获取指定位置上的元素值
String fruit = list.get(1); // 获取索引为1的元素,即第二个元素的值,Banana
//设置指定位置上的元素值
list.set(1, "grape"); // 将索引为1的元素值设置为 "grape"
//移除指定位置上的元素
String removed = list.remove(0); // 移除索引为0的元素,并返回被移除的元素值
//检查是否包含某个元素
boolean contains = list.contains("apple");
//获取元素的索引
int index = list.indexOf("orange");
//判断 ArrayList 是否为空
boolean isEmpty = list.isEmpty();
//清空 ArrayList
list.clear();
//迭代 ArrayList
for (String item : list) {
System.out.println(item);
}
Iterator<String> iterator = list.iterator();// 或者使用迭代器
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
//将 ArrayList 转换为数组
String[] array = list.toArray(new String[0]);
}
}
其他注意事项:
ArrayList
允许存储重复元素。- 当需要频繁进行插入和删除操作时,
ArrayList
比较适合,因为它提供了在末尾进行快速插入和删除的能力。 ArrayList
不是线程安全的,如果需要在多线程环境中使用,应当考虑使用Vector
类或者使用Collections.synchronizedList()
方法包装ArrayList
。- 在 ArrayList 中使用
for
循环时要注意不要在循环内修改列表,否则可能会导致ConcurrentModificationException
异常。
3. LinkedList 类
双向链表:LinkedList
是双向链表的实现,每个节点都包含指向前一个节点和后一个节点的引用。
插入和删除效率高:由于链表的特性,LinkedList
在插入和删除元素时效率比较高,因为只需要调整相邻节点的引用。
随机访问效率低:与数组相比,LinkedList
的随机访问效率较低,因为需要遍历链表来找到特定索引位置的元素。
常用方法:
-
添加元素:
add(E e)
: 在链表末尾添加元素。add(int index, E element)
: 在指定索引位置插入元素。
-
获取元素:
get(int index)
: 获取指定索引位置的元素。
-
删除元素:
remove()
: 删除并返回链表的第一个元素。remove(int index)
: 删除指定索引位置的元素。
-
修改元素:
set(int index, E element)
: 将指定索引位置的元素替换为新元素。
-
其他操作:
size()
: 返回链表的大小。clear()
: 清空链表。contains(Object o)
: 判断链表是否包含某个元素。isEmpty()
: 判断链表是否为空。
示例代码:
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<>();
// 添加元素
linkedList.add("A");
linkedList.add("B");
linkedList.add("C");
// 在指定位置插入元素
linkedList.add(1, "D");
// 获取元素
String firstElement = linkedList.get(0);
System.out.println("First element: " + firstElement);
// 删除元素
linkedList.remove(); // 删除第一个元素
linkedList.remove(1); // 删除索引为1的元素
// 修改元素
linkedList.set(0, "E");
// 遍历元素
for (String element : linkedList) {
System.out.println(element);
}
}
}
注意:
LinkedList
是一个灵活的数据结构,在某些场景下特别有用(比如队列),尤其是在需要频繁插入和删除元素的情况下。然而,在需要频繁进行随机访问时,ArrayList
更适合,因为它的访问效率更高。
4. Vector 类
Vector
是 Java 中早期的列表实现类,它与 ArrayList 类似,但是 Vector 是线程安全的,支持同步访问。
示例:
import java.util.Vector;
import java.util.List;
public class VectorExample {
public static void main(String[] args) {
List<String> vector = new Vector<>();
vector.add("Apple");
vector.add("Banana");
vector.add("Orange");
System.out.println(vector); // 输出: [Apple, Banana, Orange]
}
}
二、Set接口与实现类
理解 Set 接口以及其实现类 HashSet、LinkedHashSet 和 TreeSet 是 Java 集合框架中的重要部分。Set 是一种集合,它代表一组不重复的元素。HashSet、LinkedHashSet 和 TreeSet 分别是 Set 接口的具体实现,它们提供了不同的行为和性能特点。下面是关于 Set 接口及其实现类的详细学习内容:
1. Set 接口
- Set 接口是 Collection 接口的子接口,表示一组不包含重复元素的集合。
- Set 集合通常用于存储需要保持唯一性的元素,它不允许包含重复的元素。
- Set 接口没有定义额外的方法,它继承自 Collection 接口,并重写了部分方法以确保不会添加重复的元素。
Collection
接口是 Java 集合框架中的一个核心接口,它代表了一组对象,这些对象被称为集合元素。Collection
接口定义了一系列操作集合的方法,包括添加、删除、遍历等。所有实现了Collection
接口的类都是集合类,它们存储着一组对象,并提供了对这些对象进行操作的方法。
Collection
接口是 Java 集合框架中的根接口之一,它的子接口包括List
、Set
和Queue
。这些子接口分别表示了列表、集合和队列等不同类型的集合,而各种集合类实现了这些接口,为程序员提供了丰富的选择。通过使用
Collection
接口,Java 程序员可以编写更加通用和灵活的代码,因为它们可以以统一的方式操作不同类型的集合,而不需要关心具体的集合实现类。这种面向接口的编程方式也有助于提高代码的可维护性和可扩展性。
示例:
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 不会添加重复元素
System.out.println(set); // 输出:[banana, apple]
Set<String> set = new HashSet<>();
:
- 创建了一个
HashSet
对象,并使用泛型来指定集合中元素的类型为String
。- 使用
Set
接口来声明,这意味着set
变量可以引用任何实现了Set
接口的集合类的对象,但在此处我们选择了HashSet
。
set.add("apple");
和set.add("banana");
:
- 向
set
集合中添加了两个字符串元素,分别是 "apple" 和 "banana"。
set.add("apple");
:
- 再次尝试将 "apple" 添加到集合中,由于
HashSet
的特性是不允许重复元素存在,因此这次添加操作不会成功。
System.out.println(set);
:
- 使用
println()
方法将集合中的元素打印到控制台上。- 由于
HashSet
保证了元素的无序性,因此输出的顺序可能与添加元素的顺序不同。- 输出结果为
[banana, apple]
,这表明集合中的元素只包含一次 "banana" 和一次 "apple",并且顺序可能与添加时的顺序不同。总之,这段代码展示了
HashSet
的一个关键特性,即它不允许重复元素存在,并且通过这个特性确保了集合中不会包含重复的字符串元素。
2. HashSet
- HashSet 是 Set 接口的一个实现类,它基于哈希表实现。
- HashSet 不保证集合中元素的顺序,允许包含一个 null 元素。
- HashSet 提供了常数时间的基本操作(add、remove、contains 和 size),因此在插入、删除和查找操作上具有高效性能。
add(E e)
:该方法用于将指定的元素添加到集合中。在 HashSet 中,添加元素时,如果该元素已经存在,则不会重复添加,因为 HashSet 不允许重复元素存在。如果成功添加了元素,则返回true
;如果元素已经存在于集合中,则返回false
。
remove(Object o)
:该方法用于从集合中移除指定的元素。如果集合中存在该元素,则将其移除并返回true
;如果集合中不存在该元素,则返回false
。
contains(Object o)
:该方法用于检查集合中是否包含指定的元素。如果集合中包含该元素,则返回true
;否则返回false
。
size()
:该方法用于获取集合中的元素数量。返回值是集合中包含的元素数量。这些基本操作方法是 Java 集合框架中最常用的方法之一,在操作集合时经常会用到。在上述代码中,这些方法被用于操作 HashSet 集合对象,以添加、移除、检查元素以及获取集合大小。
示例:
Set<Integer> set = new HashSet<>();
set.add(10);
set.add(20);
set.add(30);
System.out.println(set); // 输出:[10, 20, 30]
3. LinkedHashSet
- LinkedHashSet 是 HashSet 的一个子类,它使用链表维护元素的顺序,同时使用哈希表来实现集合的唯一性。
- LinkedHashSet 保留元素插入的顺序,因此迭代顺序与插入顺序一致。
- LinkedHashSet 也允许包含一个 null 元素。
示例:
Set<String> set = new LinkedHashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 不会添加重复元素
System.out.println(set); // 输出:[apple, banana]
4. TreeSet
- TreeSet 是 Set 接口的另一个实现类,它基于红黑树(Red-Black Tree)实现。
- TreeSet 保证元素以升序或自定义排序顺序存储,因此具有有序性。
- TreeSet 不允许包含 null 元素,因为它会使用自然排序或者自定义排序来进行排序。
示例:
Set<Integer> set = new TreeSet<>();
set.add(30);
set.add(10);
set.add(20);
System.out.println(set); // 输出:[10, 20, 30]
三、Queue接口与实现类
1.Queue接口
Queue
接口代表了一种队列数据结构,它通常按照先进先出(FIFO)的顺序处理元素。在Java中,Queue
接口扩展了 Collection
接口,提供了用于操作队列的一组方法。
以下是一些 Queue
接口的主要方法:
-
add(E e): 将指定的元素添加到队列尾部,如果队列已满则抛出异常。
-
offer(E e): 将指定的元素添加到队列尾部,如果队列已满则返回 false。
-
remove(): 移除并返回队列头部的元素,如果队列为空则抛出异常。
-
poll(): 移除并返回队列头部的元素,如果队列为空则返回 null。
-
element(): 返回队列头部的元素但不移除,如果队列为空则抛出异常。
-
peek(): 返回队列头部的元素但不移除,如果队列为空则返回 null。
Queue
接口有多种实现类,其中常见的有:
- LinkedList: 基于链表的实现,支持在队列的两端进行操作,可用作队列或栈。
- ArrayDeque: 基于数组的双端队列实现,支持高效的插入、删除和检索操作。
- PriorityQueue: 基于优先级堆的实现,按照自然顺序或指定的比较器对元素进行排序。
Queue
接口通常用于模拟真实生活中的队列行为,例如任务调度、事件处理等场景。通过使用 Queue
接口,我们可以轻松地管理元素的顺序,并在需要时按照特定规则处理它们。
2. LinkedList
LinkedList
是基于链表的实现,它实现了 Queue
接口。由于它是一个双向链表,因此可以在队列的两端进行操作即双端队列。在 LinkedList
中,元素的插入和删除操作是高效的,但随机访问元素的性能较差。
下面是一个使用 LinkedList
作为队列的例子:
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListQueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// 添加元素到队列尾部
queue.add("Apple");
queue.add("Banana");
queue.add("Orange");
// 移除并返回队列头部的元素
String removedElement = queue.remove();
System.out.println("Removed element: " + removedElement);
System.out.println("Queue after removal: " + queue);
}
}
在这个例子中,我们创建了一个 LinkedList
类型的队列,并使用 add()
方法添加了几个元素。然后,我们使用 remove()
方法移除了队列的头部元素,并输出了队列内容。
2. ArrayDeque
ArrayDeque
是基于数组的双端队列实现,它同样实现了 Queue
接口。与 LinkedList
不同,ArrayDeque
在内部是基于动态数组实现的,因此在插入、删除和检索操作方面都具有高效性能。
下面是一个使用 ArrayDeque
作为队列的例子:
import java.util.ArrayDeque;
import java.util.Queue;
public class ArrayDequeQueueExample {
public static void main(String[] args) {
Queue<String> queue = new ArrayDeque<>();
// 添加元素到队列尾部
queue.add("Apple");
queue.add("Banana");
queue.add("Orange");
// 移除并返回队列头部的元素
String removedElement = queue.remove();
System.out.println("Removed element: " + removedElement);
System.out.println("Queue after removal: " + queue);
}
}
在这个例子中,我们创建了一个 ArrayDeque
类型的队列,并使用 add()
方法添加了几个元素。然后,我们使用 remove()
方法移除了队列的头部元素,并输出了队列内容。
3. PriorityQueue
PriorityQueue
是基于优先级堆的实现,它同样实现了 Queue
接口。在 PriorityQueue
中,元素被排序并按照其自然顺序或者根据指定的比较器进行排列。优先级队列允许高优先级的元素先被移除。
下面是一个使用 PriorityQueue
作为队列的例子:
import java.util.PriorityQueue;
import java.util.Queue;
public class PriorityQueueExample {
public static void main(String[] args) {
Queue<Integer> queue = new PriorityQueue<>();
// 添加元素到队列
queue.add(10);
queue.add(5);
queue.add(15);
// 移除并返回队列头部的元素
Integer removedElement = queue.remove();
System.out.println("Removed element: " + removedElement);
System.out.println("Queue after removal: " + queue);
}
}
在这个例子中,我们创建了一个 PriorityQueue
类型的队列,并使用 add()
方法添加了几个元素。由于 PriorityQueue
是基于优先级堆的实现,元素会按照其自然顺序(或者指定的比较器)进行排序。然后,我们使用 remove()
方法移除了队列的头部元素,并输出了队列内容。
四、Map接口与实现类
理解 Map 接口以及其实现类 HashMap、LinkedHashMap 和 TreeMap 是 Java 集合框架中的关键部分。Map 接口代表键值对的集合,其中每个键都是唯一的,并且每个键都映射到一个值。HashMap、LinkedHashMap 和 TreeMap 是 Map 接口的具体实现,它们提供了不同的行为和性能特点。下面是关于 Map 接口及其实现类的详细学习内容:
1. Map 接口
- Map 接口是一个键值对的集合,每个键都是唯一的,并且每个键都映射到一个值。
- Map 接口允许使用 null 作为键,并且可以包含一个键为 null 的条目,但键的唯一性是由键对象的 equals() 和 hashCode() 方法决定的。
- Map 接口定义了许多与键值对操作相关的方法,如 put(key, value)、get(key)、containsKey(key)、containsValue(value) 等。
示例:
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 15);
System.out.println(map.get("apple")); // 输出:10
2. HashMap
1. HashMap 概述
HashMap
基于哈希表实现,它使用键值对的方式存储数据,其中每个键都是唯一的。HashMap
不保证键值对的顺序,也不保证在迭代时的顺序。如果需要有序的键值对集合,可以考虑使用LinkedHashMap
。HashMap
允许使用null
作为键,但只允许有一个键为null
。HashMap
的实现是非同步的,如果需要在多线程环境中使用,可以考虑使用ConcurrentHashMap
。- HashMap 提供了常数时间的基本操作(put、get、containsKey 和 remove),因此在插入、删除和查找操作上具有高效性能。
2. HashMap 常用方法
put(K key, V value)
:将指定的键值对添加到 HashMap 中。如果键已经存在,则将新值替换旧值,并返回旧值;如果键不存在,则返回null
。get(Object key)
:返回指定键所映射的值,如果键不存在,则返回null
。remove(Object key)
:从 HashMap 中删除指定键的映射关系,并返回该键所映射的值。如果键不存在,则返回null
。containsKey(Object key)
:判断 HashMap 中是否包含指定的键。containsValue(Object value)
:判断 HashMap 中是否包含指定的值。size()
:返回 HashMap 中键值对的数量。isEmpty()
:判断 HashMap 是否为空。clear()
:清空 HashMap 中的所有键值对。getOrDefault(Object key, V defaultValue)
方法是从 Map 中获取指定键 (key
) 对应的值。如果 Map 中包含这个键,它就返回键对应的值;如果 Map 不包含这个键,它就返回一个预设的默认值 (defaultValue
)。这个方法简化了以前需要手动检查键是否存在于 Map 中的代码逻辑。
3. 示例代码
下面是一个简单的示例代码,演示了如何使用 HashMap
存储和操作键值对:
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
// 创建一个 HashMap 对象
HashMap<String, Integer> hashMap = new HashMap<>();
// 添加键值对到 HashMap 中
hashMap.put("apple", 10);
hashMap.put("banana", 20);
hashMap.put("cherry", 30);
// 获取键对应的值
int value = hashMap.get("banana");
System.out.println("Value for key 'banana': " + value);
// 判断键是否存在
boolean containsKey = hashMap.containsKey("apple");
System.out.println("Contains key 'apple': " + containsKey);
// 删除键值对
int removedValue = hashMap.remove("banana");
System.out.println("Removed value for key 'banana': " + removedValue);
// 获取 HashMap 的大小
int size = hashMap.size();
System.out.println("Size of HashMap: " + size);
}
}
3. LinkedHashMap
- LinkedHashMap 是 HashMap 的一个子类,它保留了元素的插入顺序。
- LinkedHashMap 使用双向链表维护插入顺序,因此迭代顺序与插入顺序一致。
- LinkedHashMap 允许使用 null 作为键和值。
示例:
Map<String, Integer> map = new LinkedHashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 15);
System.out.println(map); // 输出:{apple=10, banana=20, orange=15}
4. TreeMap
- TreeMap 是 Map 接口的另一个实现类,它基于红黑树(Red-Black Tree)实现。
- TreeMap 保证元素以升序或自定义排序顺序存储,因此具有有序性。
- TreeMap 不允许使用 null 作为键,因为它会使用自然排序或者自定义排序来进行排序。
示例:
Map<String, Integer> map = new TreeMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 15);
System.out.println(map); // 输出:{apple=10, banana=20, orange=15}
五、集合的遍历与操作:迭代器、增强for循环、集合工具类
理解集合的遍历和操作是 Java 编程中非常重要的一部分,它们涉及到访问和处理集合中的元素。在 Java 中,常见的集合遍历和操作包括使用迭代器、增强 for 循环以及集合工具类。下面是关于集合遍历和操作的详细学习内容:
1. 迭代器(Iterator)
- 迭代器是集合框架中的一种接口,用于迭代访问集合中的元素。
- 迭代器提供了一种统一的方式来访问各种不同类型的集合,包括列表、集合和映射等。
- 迭代器通常提供了 hasNext() 和 next() 方法来遍历集合中的元素,以及 remove() 方法来删除迭代器当前位置的元素(可选操作)。
示例:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
2. 增强 for 循环(Enhanced for Loop)
- 增强 for 循环是 Java 5 中引入的一种语法,用于简化数组和集合的遍历操作。
- 增强 for 循环提供了一种更加简洁的语法来遍历数组和集合中的元素,不需要显式使用迭代器或索引。
示例:
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("cherry");
for (String fruit : list) {
System.out.println(fruit);
}
3. 集合工具类(Collections Utility Class)
- Java 提供了
java.util.Collections
类,其中包含了许多静态方法,用于操作集合对象。 - 集合工具类提供了一系列方法来对集合进行排序、查找、替换、填充、反转等操作。
示例:
List<Integer> numbers = new ArrayList<>();
numbers.add(3);
numbers.add(1);
numbers.add(2);
Collections.sort(numbers); // 排序
System.out.println(numbers); // 输出:[1, 2, 3]
int index = Collections.binarySearch(numbers, 2); // 二分查找
System.out.println("Index of 2: " + index); // 输出:1
Collections.reverse(numbers); // 反转
System.out.println(numbers); // 输出:[3, 2, 1]