Java集合(collections)框架提供了一组接口和类,以实现各种数据结构和算法。例如,集合框架的LinkedList类提供了双向链接列表数据结构的实现。

Collection 接口

Collection接口是集合框架的root根接口.

Java不提供Collection接口的直接实现,但是提供其子接口(如ListSetQueue)的实现。

Collections 框架 Vs. Collection 接口

人们会对 Collections框架Collection接口感到迷惑.

Collection接口collections框架的根接口。该框架还包括其他接口:MapIterator,这些接口也可以具有子接口。

Collections接口的子接口

如前所述,Collection接口包括由Java类实现的子接口。

Collection接口的所有方法也都存在于其子接口中。

这是收集接口的子接口:

List Interface

List接口是一个有序的集合,它允许我们添加和删除数组之类的元素。

Set Interface

Set接口允许我们将元素存储在不同的集合中,类似于数学中的集合。它不能有重复的元素。

Queue Interface

当我们要以First In, First Out(FIFO)(先进先出)的方式存储和访问元素时,可以使用Queue接口

Map Interface

在Java中,Map接口允许将元素存储在key/value对中。key是唯一的名称,可用于访问Map中的特定元素。

Iterator Interface

在Java中,Iterator接口提供了可用于访问集合元素的方法。

为什么用 Collections 框架

Java集合框架提供了可以直接使用的各种数据结构和算法。这有两个主要优点:

  • 我们不必编写代码即可手动实现这些数据结构和算法。
  • 随着集合框架的高度优化,我们的代码将更加高效。

此外,集合框架允许我们对特定类型的数据使用特定的数据结构。这里有一些例子:

  1. 如果我们希望数据唯一,则可以使用collections框架提供的Set接口
  2. 要将数据存储在key/value对中,我们可以使用Map接口
  3. ArrayList类提供可调整大小的数组的功能。

Collections例子: ArrayList Class

ArrayList类允许我们创建可调整大小的数组。该类实现List接口(这是Collection接口的子接口)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// The Collections framework is defined in the java.util package
import java.util.ArrayList;

class Main {
public static void main(String[] args){
ArrayList<String> animals = new ArrayList<>();
// Add elements
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");

System.out.println("ArrayList: " + animals);
}
}

输出:

1
ArrayList: [Dog, Cat, Horse]

Collection 中的方法

Collection接口包括各种方法,可用于对对象执行不同的操作.这些方法在其所有子接口中均可用。

  • add() - 将指定的元素插入到集合中
  • size() - 返回集合的大小
  • remove() - 从集合中删除指定的元素
  • iterator() - 返回用于访问集合元素的迭代器
  • addAll() - 将指定集合的所有元素添加到集合中
  • removeAll() - 从集合中删除指定集合的所有元素
  • clear() - 删除集合的所有元素

Java List

在Java中,List接口是一个有序的集合,允许我们按顺序存储和访问元素。它扩展了Collection接口

实现List接口的类

由于List是一个接口,因此我们无法从中创建对象。为了使用List接口的功能,我们可以使用以下类:

这些类在Collections框架中定义,并实现List接口

如何使用List

在Java中,必须导入java.util.List包才能使用List

1
2
3
4
5
// ArrayList implementation of List
List<String> list1 = new ArrayList<>();

// LinkedList implementation of List
List<String> list2 = new LinkedList<>();

在这里,我们创建了ArrayListLinkedList类的对象list1list2。这些对象可以使用List接口的功能。

List 中的方法

List接口包括Collection接口的所有方法。这是因为CollectionList的父级接口。

List接口中还提供了Collection接口的一些常用方法:

  • add() - 向list添加一个元素.

  • addAll() - 将一个列表中的所有元素添加进另一个列表中.

  • get() - 帮助随机访问列表中的元素.

  • iterator() - 返回可用于顺序访问列表元素的迭代器对象.

  • set() - 更改列表元素.

  • remove() - 从列表中删除一个元素.

  • removeAll() - 从列表中删除所有元素.

  • clear() - 从列表中删除所有元素(比removeAll()更有效).

  • size() - 返回列表的长度.

  • toArray() - 将列表转换为数组.

  • contains() - 如果列表包含指定的元素,则返回true.

List 接口的实现

ArrayList 类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.List;
import java.util.ArrayList;

class Main {

public static void main(String[] args) {
// Creating list using the ArrayList class
List<Integer> numbers = new ArrayList<>();

// Add elements to the list
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("List: " + numbers);

// Access element from the list
int number = numbers.get(2);
System.out.println("Accessed Element: " + number);

// Remove element from the list
int removedNumber = numbers.remove(1);
System.out.println("Removed Element: " + removedNumber);
}
}

输出:

1
2
3
List: [1, 2, 3]
Accessed Element: 3
Removed Element: 2

LinkedList类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.List;
import java.util.LinkedList;

class Main {

public static void main(String[] args) {
// Creating list using the LinkedList class
List<Integer> numbers = new LinkedList<>();

// Add elements to the list
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("List: " + numbers);

// Access element from the list
int number = numbers.get(2);
System.out.println("Accessed Element: " + number);

// Using the indexOf() method
int index = numbers.indexOf(2);
System.out.println("Position of 3 is " + index);

// Remove element from the list
int removedNumber = numbers.remove(1);
System.out.println("Removed Element: " + removedNumber);
}
}

输出:

1
2
3
4
List: [1, 2, 3]
Accessed Element: 3
Position of 3 is 1
Removed Element: 2

Java List VS Set

List接口和Set接口都继承了Collection接口。但是,它们之间存在一些差异。

  1. List可以包含重复的元素。但是,Set`不能有重复的元素。
  2. List中的元素以某种顺序存储。但是,Set中的元素像数学中的集合一样按组存储。

Java ArrayList

ArrayList类,在Java集合框架中提供了可以调整数组大小功能.

ArrayList Vs Array

在Java中, 我们需要先声明数组的大小,再使用它.当数组的大小一旦定义,你就很难去改变它.

为了解决这个问题,我们可以使用ArrayList,它允许我们创建可调整大小的数组。

ArrayList会自动的在我们新增或删除元素的时候动态调整它的大小.因此ArrayList也被称为动态数组.

创建 一个ArrayList

在使用ArrayList之前,我们需要首先导入java.util.ArrayList包。

创建arraylist语法:

1
ArrayList<Type> arrayList= new ArrayList<>();

Type表示arrayList中元素类型.

1
2
3
4
5
// create Integer type arraylist
ArrayList<Integer> arrayList = new ArrayList<>();

// create String type arraylist
ArrayList<String> arrayList = new ArrayList<>();

在上面的程序中,我们使用了Integer 并不能进行初始化。这是因为我们在创建arraylist时不能使用基本类型。我们应该使用相应的包装器类

例子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.ArrayList;

class Main {
public static void main(String[] args){

// create ArrayList
ArrayList<String> languages = new ArrayList<>();

// Add elements to ArrayList
languages.add("Java");
languages.add("Python");
languages.add("Swift");
System.out.println("ArrayList: " + languages);
}
}

输出:

1
ArrayList: [Java, Python, Swift]

在上面的示例中,我们创建了一个名为languageArrayList

在这里,我们使用了add()方法将元素添加到arraylist中。

我们还可以使用List接口创建一个arraylist。这是因为ArrayList类实现了List接口。

1
List<String> list = new ArrayList<>();

ArrayList 基本操作

ArrayList提供了各种对arraylist操作的方法.

添加元素到 ArrayList

要将单个元素添加到arraylist,我们使用ArrayList类的add()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;

class Main {
public static void main(String[] args){
// create ArrayList
ArrayList<String> languages = new ArrayList<>();

// add() method without the index parameter
languages.add("Java");
languages.add("C");
languages.add("Python");
System.out.println("ArrayList: " + languages);

// add() method with the index parameter
languages.add(1, "JavaScript");
System.out.println("Updated ArrayList: " + languages);
}
}

输出:

1
2
ArrayList: [Java, C, Python]
Updated ArrayList: [Java, JavaScript, C, Python]

在上面的示例中,我们创建了一个名为languageArrayList。在这里,我们使用add()方法将元素添加到语言中。

注意声明:

1
languages.add(1, "JavaScript");

在这里,我们使用了索引号参数。它是一个可选参数,用于指定添加新元素的位置。

获取ArrayList中一个元素

要访问arraylist中的元素,我们使用ArrayList类的get()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
ArrayList<String> animals = new ArrayList<>();

// add elements in the arraylist
animals.add("Cat");
animals.add("Dog");
animals.add("Cow");
System.out.println("ArrayList: " + animals);

// get the element from the arraylist
String str = animals.get(1);
System.out.print("Element at index 1: " + str);
}
}

输出

1
2
ArrayList: [Cat, Dog, Cow]
Element at index 1: Dog

在上面的示例中,我们使用了带有参数1get()方法。这里,该方法返回索引为1的元素。

修改ArrayList中的元素

要更改arraylist的元素,我们使用ArrayList类的set()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
ArrayList<String> languages = new ArrayList<>();

// add elements in the array list
languages.add("Java");
languages.add("Kotlin");
languages.add("C++");
System.out.println("ArrayList: " + languages);

// change the element of the array list
languages.set(2, "JavaScript");
System.out.println("Modified ArrayList: " + languages);
}
}

输出:

1
2
ArrayList: [Java, Kotlin, C++]
Modified ArrayList: [Java, Kotlin, JavaScript]

在上面的示例中,我们创建了一个名为language的ArrayList。但是通过language.set(2,'JavaScript').我们修改了下标2的元素值为JavaScript.

移除ArrayList中元素

要从arraylist中删除一个元素,我们可以使用ArrayList类的remove()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
ArrayList<String> animals = new ArrayList<>();

// add elements in the array list
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayList: " + animals);

// aemove element from index 2
String str = animals.remove(2);
System.out.println("Updated ArrayList: " + animals);
System.out.println("Removed Element: " + str);
}
}

输出

1
2
3
ArrayList: [Dog, Cat, Horse]
Updated ArrayList: [Dog, Cat]
Removed Element: Horse

在这里,remove()方法将索引号作为参数,删除索引编号下的元素.

ArrayList中的常用方法

Methods Descriptions
size() 返回arraylist长度
sort() 对arraylist元素进行排序。
clone() 创建一个具有相同元素,大小和容量的新arraylist。
contains() 在arraylist中搜索指定的元素并返回布尔结果。
ensureCapacity() 指定arraylist可以包含的总元素。
isEmpty() 检查arraylist是否为空。
indexOf() 在数组列表中搜索指定的元素,并返回该元素的索引。

遍历ArrayList

可以使用for-each遍历ArrayList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayList;

class Main {
public static void main(String[] args) {

// creating an array list
ArrayList<String> languages = new ArrayList<>();
languages.add("Cow");
languages.add("Cat");
languages.add("Dog");
System.out.println("ArrayList: " + languages);

// iterate using for-each loop
System.out.println("Accessing individual elements: ");

for (String language : languages) {
System.out.print(language);
System.out.print(", ");
}
}
}

输出:

1
2
3
ArrayList: [Cow, Cat, Dog]
Accessing individual elements:
Cow, Cat, Dog,

ArrayList转成Array

我们可以使用toArray()方法将ArrayList转换为Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
ArrayList<String> languages = new ArrayList<>();

// add elements in the array list
languages.add("Java");
languages.add("Python");
languages.add("C++");
System.out.println("ArrayList: " + languages);

// create a new array of String type
String[] arr = new String[languages.size()];

// convert ArrayList into an array
languages.toArray(arr);
System.out.print("Array: ");

// access elements of the array
for (String item : arr) {
System.out.print(item + ", ");
}
}
}

输出:

1
2
ArrayList: [Java, Python, C++]
Array: Java, Python, C++,

在上面的示例中,我们创建了一个名为language的数组列表。注意声明:

1
languages.toArray(arr);

在这里,toArray()方法将arraylist转换为数组并将其存储在arr中。

Array转成ArrayList

我们还可以将Array转换为arraylist。为此,我们使用Arrays类的asList()方法。

要使用asList(),我们必须首先导入java.util.Arrays包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayList;
import java.util.Arrays;

class Main {
public static void main(String[] args) {

// create an array of String type
String[] arr = { "Java", "Python", "C++" };
System.out.print("Array: ");

// print array
for (String str : arr) {
System.out.print(str);
System.out.print(" ");
}

// create an ArrayList from an array
ArrayList<String> languages = new ArrayList<>(Arrays.asList(arr));
System.out.println("\nArrayList: " + languages);
}
}

输出:

1
2
Array: Java Python C++        
ArrayList: [Java, Python, C++]

注意:我们还可以使用Arrays.asList()方法在一行中创建和初始化arraylist。例如,

1
ArrayList<String> animals = new ArrayList<>(Arrays.asList("Cat", "Cow", "Dog"));

ArrayList转成 String

我们可以使用ArrayList类的toString()方法将arraylist转换为字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
ArrayList<String> languages = new ArrayList<>();

// add elements in the ArrayList
languages.add("Java");
languages.add("Python");
languages.add("Kotlin");
System.out.println("ArrayList: " + languages);

// convert ArrayList into a String
String str = languages.toString();
System.out.println("String: " + str);
}
}

输出:

1
2
ArrayList: [Java, Python, Kotlin]
String: [Java, Python, Kotlin]

在这里,toString()方法将整个arraylist转换为单个字符串。

Java Vector

Vector类是List接口的一种实现,它使我们可以创建类似于ArrayList类的可调整大小的数组。

Vectorvs.ArrayList

ArrayListVector均实现List接口并提供相同的功能。但是,它们之间存在一些差异。

Vector类同步每个单独的操作。这意味着每当我们要对向量执行某些操作时,Vector类都会自动对该操作施加锁定。

这是因为当一个线程正在访问向量时,同时另一个线程试图访问它时,会生成一个称为ConcurrentModificationException的异常。但是这样每次操作进行锁操作会降低整个的性能.

但是,在array list中方法不同步。但可以使用Collections.synchronizedList()方法将整个列表同步。

注意:建议使用ArrayList代替Vector,因为矢量不是线程安全的,并且效率较低。

创建 一个 Vector

1
Vector<Type> vector = new Vector<>();

此处,Type表示链接列表的类型。

1
2
3
4
5
// create Integer type linked list
Vector<Integer> vector= new Vector<>();

// create String type linked list
Vector<String> vector= new Vector<>();

Vector中的方法

Vector类还提供List接口的可调整大小的数组实现(类似于ArrayList类)。一些Vector方法是:

Vector中添加元素

  • add(element) - 向Vector中添加元素.
  • add(index,element) - 向Vector中指定位置添加元素.
  • addAll(vector) - 将一个Vector中所有元素添加另一个Vector中.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Vector;

class Main {
public static void main(String[] args) {
Vector<String> mammals= new Vector<>();

// Using the add() method
mammals.add("Dog");
mammals.add("Horse");

// Using index number
mammals.add(2, "Cat");
System.out.println("Vector: " + mammals);

// Using addAll()
Vector<String> animals = new Vector<>();
animals.add("Crocodile");

animals.addAll(mammals);
System.out.println("New Vector: " + animals);
}
}

输出:

1
2
Vector: [Dog, Horse, Cat]
New Vector: [Crocodile, Dog, Horse, Cat]

获取Vector中的元素

  • get(index) - 返回指定下标下的元素
  • iterator() - 返回一个迭代器对象以顺序访问vector中元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Iterator;
import java.util.Vector;

class Main {
public static void main(String[] args) {
Vector<String> animals= new Vector<>();
animals.add("Dog");
animals.add("Horse");
animals.add("Cat");

// Using get()
String element = animals.get(2);
System.out.println("Element at index 2: " + element);

// Using iterator()
Iterator<String> iterate = animals.iterator();
System.out.print("Vector: ");
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
Element at index 2: Cat
Vector: Dog, Horse, Cat,

移除Vector中的元素

  • remove(index) - 从指定位置删除元素.
  • removeAll() - 移除所有的元素.
  • clear() - 删除所有元素。它比removeAll()性能更好.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Vector;

class Main {
public static void main(String[] args) {
Vector<String> animals= new Vector<>();
animals.add("Dog");
animals.add("Horse");
animals.add("Cat");

System.out.println("Initial Vector: " + animals);

// Using remove()
String element = animals.remove(1);
System.out.println("Removed Element: " + element);
System.out.println("New Vector: " + animals);

// Using clear()
animals.clear();
System.out.println("Vector after clear(): " + animals);
}
}

输出:

1
2
3
4
Initial Vector: [Dog, Horse, Cat]
Removed Element: Horse
New Vector: [Dog, Cat]
Vector after clear(): []

其它Vector方法

Methods Descriptions
set() 更改Vector的元素
size() 返回Vector中的大小
toArray() Vector转换为数组
toString() Vector转换为字符串
contains() Vector中搜索指定的元素并返回布尔结果

Stack

Java集合框架具有一个名为Stack的类,该类提供堆栈数据结构的功能。

Stack类扩展了Vector类。

Stack 实现

Stack中元素遵循Last In First Out后进先出的原则.元素被添加到堆栈的顶部,并从堆栈的顶部移除。

创建一个 Stack

为了创建堆栈,我们必须首先导入java.util.Stack包。导入包后,就可以使用Java创建堆栈。

1
Stack<Type> stacks = new Stack<>();

在这里,Type表示堆栈的类型

1
2
3
4
5
// Create Integer type stack
Stack<Integer> stacks = new Stack<>();

// Create String type stack
Stack<String> stacks = new Stack<>();

Stack 中的方法

由于Stack扩展了Vector类,因此它继承了Vector的所有方法。

除了这些方法之外,Stack类还包括5个与Vector区别开来的方法。

push() 方法

要将元素添加到stack的顶部,我们使用push()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack
animals.push("Dog");
animals.push("Horse");
animals.push("Cat");

System.out.println("Stack: " + animals);
}
}

输出:

1
Stack: [Dog, Horse, Cat]

pop() 方法

若要从堆栈顶部删除元素,我们使用 pop() 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack
animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
System.out.println("Initial Stack: " + animals);

// Remove element stacks
String element = animals.pop();
System.out.println("Removed Element: " + element);
}
}

输出:

1
2
Initial Stack: [Dog, Horse, Cat]
Removed Element: Cat

peek() 方法

peek() 方法从堆栈顶部返回对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack
animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
System.out.println("Stack: " + animals);

// Access element from the top
String element = animals.peek();
System.out.println("Element at top: " + element);

}
}

输出:

1
2
Stack: [Dog, Horse, Cat]
Element at top: Cat

search 方法

若要搜索堆栈中的元素,我们使用 search() 方法。它会返回元素所在下标.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack
animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
System.out.println("Stack: " + animals);

// Search an element
int position = animals.search("Horse");
System.out.println("Position of Horse: " + position);
}
}

输出:

1
2
Stack: [Dog, Horse, Cat]
Position of Horse: 2

empty()方法

为了检查堆栈是否为空,我们使用 empty() 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Stack;

class Main {
public static void main(String[] args) {
Stack<String> animals= new Stack<>();

// Add elements to Stack
animals.push("Dog");
animals.push("Horse");
animals.push("Cat");
System.out.println("Stack: " + animals);

// Check if stack is empty
boolean result = animals.empty();
System.out.println("Is the stack empty? " + result);
}
}

输出:

1
2
Stack: [Dog, Horse, Cat]
Is the stack empty? false

ArrayDeque替代Stack

Stack类提供了堆栈数据结构的直接实现。但是,建议不要使用它。而是使用ArrayDeque类(实现Deque接口).在Java中实现堆栈数据结构。

Queue 接口

Java collections框架通过Queue接口提供了队列数据结构的功能。它继承至Collection.

实现Queue的接口

为了使用Queue的功能,我们需要使用实现它的类:

扩展Queue的接口

Queue接口还通过各种子接口扩展:

  • Deque
  • BlockingQueue
  • BlockingDeque

Queue数据结构工作模式

Queue队列中,以(First In, First Out)先进先出的方式存储和访问元素。

元素从后面添加,从前面删除。

怎么使用队列

在Java中,必须导入java.util.Queue包才能使用Queue

1
2
3
4
5
6
7
8
9

// LinkedList implementation of Queue
Queue<String> animal1 = new LinkedList<>();

// Array implementation of Queue
Queue<String> animal2 = new ArrayDeque<>();

// Priority Queue implementation of Queue
Queue<String> animal 3 = new PriorityQueue<>();

在这里,我们分别创建了类LinkedListArrayDequePriorityQueue的对象Animal1Animal2Animal3。这些对象可以使用Queue接口的功能。

Queue中的方法

Queue接口包括Collection接口的所有方法。

Queue接口的一些常用方法是:

  • add() - 将指定的元素插入队列。如果任务成功,则add()返回true,否则返回异常。
  • offer() - 将指定的元素插入队列。如果任务成功,则offer()返回true,否则返回false。
  • element() - 返回队列的头元素。如果队列为空,则引发异常。
  • peek() - 返回队列的头元素。如果队列为空,则返回null。
  • remove() - 返回并删除队列的头元素。如果队列为空,则引发异常。
  • poll() - 返回并删除队列的头元素.如果队列为空,则返回null。

实现Queue接口

LinkedList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.Queue;
import java.util.LinkedList;

class Main {

public static void main(String[] args) {
// Creating Queue using the LinkedList class
Queue<Integer> numbers = new LinkedList<>();

// offer elements to the Queue
numbers.offer(1);
numbers.offer(2);
numbers.offer(3);
System.out.println("Queue: " + numbers);

// Access elements of the Queue
int accessedNumber = numbers.peek();
System.out.println("Accessed Element: " + accessedNumber);

// Remove elements from the Queue
int removedNumber = numbers.poll();
System.out.println("Removed Element: " + removedNumber);

System.out.println("Updated Queue: " + numbers);
}
}

输出:

1
2
3
4
Queue: [1, 2, 3]
Accessed Element: 1
Removed Element: 1
Updated Queue: [2, 3]

PriorityQueue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.Queue;
import java.util.PriorityQueue;

class Main {

public static void main(String[] args) {
// Creating Queue using the PriorityQueue class
Queue<Integer> numbers = new PriorityQueue<>();

// offer elements to the Queue
numbers.offer(5);
numbers.offer(1);
numbers.offer(2);
System.out.println("Queue: " + numbers);

// Access elements of the Queue
int accessedNumber = numbers.peek();
System.out.println("Accessed Element: " + accessedNumber);

// Remove elements from the Queue
int removedNumber = numbers.poll();
System.out.println("Removed Element: " + removedNumber);

System.out.println("Updated Queue: " + numbers);
}
}

输出:

1
2
3
4
Queue: [1, 5, 2]
Accessed Element: 1
Removed Element: 1
Updated Queue: [2, 5]

PriorityQueue

PriorityQueue类提供堆数据结构的功能。

与普通队列不同,优先级队列元素是按排序顺序检索的。

假设我们要按升序检索元素。在这种情况下,优先级队列的头部将是最小的元素。一旦检索到此元素,下一个最小的元素将是队列的开头。

重要的是要注意,优先级队列的元素可能未排序。但是,元素总是按排序顺序检索。

创建 PriorityQueue

为了创建优先级队列,我们必须导入java.util.PriorityQueue包。导入程序包后,可以使用以下方法在Java中创建优先级队列。

1
PriorityQueue<Integer> numbers = new PriorityQueue<>();

在这里,我们创建了一个没有任何参数的优先级队列。在这种情况下,优先级队列的头部是队列的最小元素。并且元素以升序从队列中删除。

但是,我们可以借助Comparator接口自定义元素的顺序。

PriorityQueue中的方法

PriorityQueue类提供了Queue接口中存在的所有方法的实现。

PriorityQueue插入元素

  • add() - 将指定的元素插入队列。如果队列已满,则将引发异常。
  • offer() - 将指定的元素插入队列。如果队列已满,则返回false。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.PriorityQueue;

class Main {
public static void main(String[] args) {

// Creating a priority queue
PriorityQueue<Integer> numbers = new PriorityQueue<>();

// Using the add() method
numbers.add(4);
numbers.add(2);
System.out.println("PriorityQueue: " + numbers);

// Using the offer() method
numbers.offer(1);
System.out.println("Updated PriorityQueue: " + numbers);
}
}

输出:

1
2
PriorityQueue: [2, 4]
Updated PriorityQueue: [1, 4, 2]

在这里,我们创建了一个名为数字的优先级队列。我们已将4和2插入队列。

尽管在2之前插入了4,但队列的开头是2。这是因为优先级队列的头是队列中最小的元素。

然后,我们将1插入队列。现在重新排列了队列,以将最小的元素1存储到队列的开头。

PriorityQueue获取元素

要访问优先级队列中的元素,我们可以使用peek()方法。此方法返回队列的头元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.PriorityQueue;

class Main {
public static void main(String[] args) {

// Creating a priority queue
PriorityQueue<Integer> numbers = new PriorityQueue<>();
numbers.add(4);
numbers.add(2);
numbers.add(1);
System.out.println("PriorityQueue: " + numbers);

// Using the peek() method
int number = numbers.peek();
System.out.println("Accessed Element: " + number);
}
}

输出:

1
2
PriorityQueue: [1, 4, 2]
Accessed Element: 1

移除PriorityQueue中的元素

  • romve() - 从队列中删除指定的元素.
  • poll() - 返回并删除队列的开头
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.PriorityQueue;

class Main {
public static void main(String[] args) {

// Creating a priority queue
PriorityQueue<Integer> numbers = new PriorityQueue<>();
numbers.add(4);
numbers.add(2);
numbers.add(1);
System.out.println("PriorityQueue: " + numbers);

// Using the remove() method
boolean result = numbers.remove(2);
System.out.println("Is the element 2 removed? " + result);

// Using the poll() method
int number = numbers.poll();
System.out.println("Removed Element Using poll(): " + number);
}
}

输出:

1
2
3
PriorityQueue: [1, 4, 2]
Is the element 2 removed? true
Removed Element Using poll(): 1

遍历 PriorityQueue

要遍历优先级队列的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.PriorityQueue;
import java.util.Iterator;

class Main {
public static void main(String[] args) {

// Creating a priority queue
PriorityQueue<Integer> numbers = new PriorityQueue<>();
numbers.add(4);
numbers.add(2);
numbers.add(1);
System.out.print("PriorityQueue using iterator(): ");

//Using the iterator() method
Iterator<Integer> iterate = numbers.iterator();
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
PriorityQueue using iterator(): 1, 4, 2,

其它PriorityQueue方法

Methods Descriptions
contains(element) 在优先级队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size() 返回优先级队列的长度。
toArray() 将优先级队列转换为数组并返回它。

PriorityQueue Comparator

Priority元素以自然顺序(升序)检索。但是,我们可以自定义此排序。

为此,我们需要创建自己的比较器类来实现Comparator接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.PriorityQueue;
import java.util.Comparator;
class Main {
public static void main(String[] args) {

// Creating a priority queue
PriorityQueue<Integer> numbers = new PriorityQueue<>(new CustomComparator());
numbers.add(4);
numbers.add(2);
numbers.add(1);
numbers.add(3);
System.out.print("PriorityQueue: " + numbers);
}
}

class CustomComparator implements Comparator<Integer> {

@Override
public int compare(Integer number1, Integer number2) {
int value = number1.compareTo(number2);
// elements are sorted in reverse order
if (value > 0) {
return -1;
}
else if (value < 0) {
return 1;
}
else {
return 0;
}
}
}

输出

1
PriorityQueue: [4, 3, 1, 2]

在上面的示例中,我们创建了一个priorty队列,将CustomComparator类作为参数传递。

CustomComparator类实现Comparator接口。

然后,我们重写compare()方法。现在,该方法使元素的头元素为最大数。

Deque接口

Java collections框架Deque提供了双端队列功能.它继承至Queue接口.

Deque工作模式

在常规队列中,元素是从后面添加的,而从前面删除的。但是,在双端队列中,我们可以从前面和后面插入和删除元素(insert and remove elements from both front and rear)

Deque接口的实现

为了使用Deque接口的功能,我们需要使用实现该接口的类:

怎么使用 Deque

在Java中,我们必须导入java.util.Deque包才能使用Deque

1
2
3
4
5
// Array implementation of Deque
Deque<String> animal1 = new ArrayDeque<>();

// LinkedList implementation of Deque
Deque<String> animal2 = new LinkedList<>();

在这里,我们分别创建了类ArrayDequeLinkedList的对象animal1animal2

Deque中的方法

Deque继承至Queue接口,它继承了所有Queue接口.

Queue接口中可用的方法外,Deque接口还包括以下方法:

  • addFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则引发异常。
  • addLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则引发异常.
  • offerFirst() - 在双端队列的开头添加指定的元素。如果双端队列已满,则返回false。
  • offerLast() - 在双端队列的末尾添加指定的元素。如果双端队列已满,则返回false。
  • getFirst() - 返回双端队列的第一个元素。如果双端队列为空,则引发异常。
  • getLast() - 返回双端队列的最后一个元素。如果双端队列为空,则引发异常。
  • peekFirst() - 返回双端队列的第一个元素。如果双端队列为空,则返回null。
  • peekLast() - 返回双端队列的最后一个元素。如果双端队列为空,则返回null。
  • removeFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则引发异常。
  • removeLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则引发异常。
  • pollFirst() - 返回并删除双端队列的第一个元素。如果双端队列为空,则返回null。
  • pollLast() - 返回并删除双端队列的最后一个元素。如果双端队列为空,则返回null。

Deque 作为堆栈数据结构

Java Collections框架的Stack类提供了堆栈的实现。

但是,建议将Deque用作堆栈而不是Stack类。这是因为Stack的方法是同步的。

以下是Deque接口提供的用于实现堆栈的方法:

  • push() - 在双端队列的开头添加一个元素
  • pop()- 从双端队列的开头删除元素
  • peek() - 从双端队列的开头返回一个元素

实现Deque了类ArrayDeque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.Deque;
import java.util.ArrayDeque;

class Main {

public static void main(String[] args) {
// Creating Deque using the ArrayDeque class
Deque<Integer> numbers = new ArrayDeque<>();

// add elements to the Deque
numbers.offer(1);
numbers.offerLast(2);
numbers.offerFirst(3);
System.out.println("Deque: " + numbers);

// Access elements of the Deque
int firstElement = numbers.peekFirst();
System.out.println("First Element: " + firstElement);

int lastElement = numbers.peekLast();
System.out.println("Last Element: " + lastElement);

// Remove elements from the Deque
int removedNumber1 = numbers.pollFirst();
System.out.println("Removed First Element: " + removedNumber1);

int removedNumber2 = numbers.pollLast();
System.out.println("Removed Last Element: " + removedNumber2);

System.out.println("Updated Deque: " + numbers);
}
}

输出:

1
2
3
4
5
6
Deque: [3, 1, 2]
First Element: 3
Last Element: 2
Removed First Element: 3
Removed Last Element: 2
Updated Deque: [1]

LinkedList

Javacollections框架的LinkedList类提供了链表数据结构(双重链表)的功能。

链表中的每个元素都称为节点。它包含3个字段:

  • Prev - 将前一个元素的地址存储在列表中。第一个元素为null
  • Next- 在列表中存储下一个元素的地址。最后一个元素为null
  • Data- 存储实际数据.

创建 Java LinkedList

这是我们如何在Java中创建链接列表的方法:

1
LinkedList<Type> linkedList = new LinkedList<>();

此处,Type表示链接列表的类型。

1
2
3
4
5
// create Integer type linked list
LinkedList<Integer> linkedList = new LinkedList<>();

// create String type linked list
LinkedList<String> linkedList = new LinkedList<>();

例子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.LinkedList;

class Main {
public static void main(String[] args){

// create linkedlist
LinkedList<String> animals = new LinkedList<>();

// Add elements to LinkedList
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
System.out.println("LinkedList: " + animals);
}
}

输出

1
LinkedList: [Dog, Cat, Cow]

在上面的示例中,我们创建了一个名为AnimalsLinkedList

在这里,我们使用add()方法将元素添加到LinkedList

LinkedList 中的工作模式

链接列表中的元素未按顺序存储。相反,它们分散并通过链接(上一个和下一个)连接。

在这里,链接列表中包含3个元素。

  • Dog - 它是第一个保留null为上一个地址,而Cat的地址为下一个地址的元素

  • Cat - 它是第二个元素,将Dog的地址作为前一个地址,将Cow的地址作为下一个地址

  • Cow-它是将Cat的地址保留为前一个地址而将null保留为下一个元素的最后一个元素

LinkedList 中的方法

LinkedList提供了多种方法,使我们可以在链表中执行不同的操作。

  • 添加 元素
  • 获取 元素
  • 修改 元素
  • 移除 元素

LinkedList中添加元素

我们可以使用add()方法在LinkedList的末尾添加一个元素(节点)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.LinkedList;

class Main {
public static void main(String[] args){
// create linkedlist
LinkedList<String> animals = new LinkedList<>();

// add() method without the index parameter
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
System.out.println("LinkedList: " + animals);

// add() method with the index parameter
animals.add(1, "Horse");
System.out.println("Updated LinkedList: " + animals);
}
}

输出:

1
2
LinkedList: [Dog, Cat, Cow]
Updated LinkedList: [Dog, Horse, Cat, Cow]

在上面的示例中,我们创建了一个名为AnimalsLinkedList。在这里,我们使用add()方法向动物添加元素。

注意:

1
animals.add(1, "Horse");

在这里,我们使用了索引号参数,它是一个可选参数,用于指定添加新元素的位置。

获取 LinkedList元素

LinkedList类的get()方法用于访问LinkedList中的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.LinkedList;

class Main {
public static void main(String[] args) {
LinkedList<String> languages = new LinkedList<>();

// add elements in the linked list
languages.add("Python");
languages.add("Java");
languages.add("JavaScript");
System.out.println("LinkedList: " + languages);

// get the element from the linked list
String str = languages.get(1);
System.out.print("Element at index 1: " + str);
}
}

输出

1
2
LinkedList: [Python, Java, JavaScript]
Element at index 1: Java

在上面的示例中,我们将get()方法的参数1一起使用。在这里,该方法返回索引为1的元素。

我们还可以使用iterator()listIterator()方法访问LinkedList的元素。

修改LinkedList中的元素

LinkedList类的set()方法用于更改LinkedList的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.LinkedList;

class Main {
public static void main(String[] args) {
LinkedList<String> languages = new LinkedList<>();

// add elements in the linked list
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
languages.add("Java");
System.out.println("LinkedList: " + languages);

// change elements at index 3
languages.set(3, "Kotlin");
System.out.println("Updated LinkedList: " + languages);
}
}

输出:

1
2
LinkedList: [Java, Python, JavaScript, Java]
Updated LinkedList: [Java, Python, JavaScript, Kotlin]
1
languages.set(3, "Kotlin");

在这里,set()方法将索引3处的元素更改为Kotlin

移除LinkedList中的元素

LinkedList类的remove()方法用于从LinkedList中删除元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.LinkedList;

class Main {
public static void main(String[] args) {
LinkedList<String> languages = new LinkedList<>();

// add elements in LinkedList
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
languages.add("Kotlin");
System.out.println("LinkedList: " + languages);

// remove elements from index 1
String str = languages.remove(1);
System.out.println("Removed Element: " + str);

System.out.println("Updated LinkedList: " + languages);
}
}

输出:

1
2
3
LinkedList: [Java, Python, JavaScript, Kotlin]
Removed Element: Python
New LinkedList: [Java, JavaScript, Kotlin]

在这里,remove()方法将索引号作为参数。并且删除索引编号指定的元素。

其它常用方法

Methods Description
contains() 检查LinkedList是否包含元素
indexOf() 返回元素第一次出现的索引
lastIndexOf() 返回元素最后一次出现的索引
clear() 删除LinkedList的所有元素
iterator() 返回用于迭代LinkedList的迭代器

LinkedList 作为 Deque 和Queue

由于LinkedList类还实现了QueueDeque接口,它也可以实现这些接口的方法。

以下是一些常用方法:

Methods Descriptions
addFirst() 将指定的元素添加到链接列表的开头
addLast() 将指定的元素添加到链接列表的末尾
getFirst() 返回第一个元素
getLast() 返回最后一个元素
removeFirst() 删除第一个元素
removeLast() 删除最后一个元素
peek() 返回链表的第一个元素(头)
poll() 返回并从链接列表中删除第一个元素
offer() 将指定的元素添加到链接列表的末尾

LinkedList 作为 Queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.LinkedList;
import java.util.Queue;

class Main {
public static void main(String[] args) {
Queue<String> languages = new LinkedList<>();

// add elements
languages.add("Python");
languages.add("Java");
languages.add("C");
System.out.println("LinkedList: " + languages);

// access the first element
String str1 = languages.peek();
System.out.println("Accessed Element: " + str1);

// access and remove the first element
String str2 = languages.poll();
System.out.println("Removed Element: " + str2);
System.out.println("LinkedList after poll(): " + languages);

// add element at the end
languages.offer("Swift");
System.out.println("LinkedList after offer(): " + languages);
}
}

输出:

1
2
3
4
5
LinkedList: [Python, Java, C]
Accessed Element: Python
Removed Element: Python
LinkedList after poll(): [Java, C]
LinkedList after offer(): [Java, C, Swift]

LinkedList as Deque

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.LinkedList;
import java.util.Deque;

class Main {
public static void main(String[] args){
Deque<String> animals = new LinkedList<>();

// add element at the beginning
animals.add("Cow");
System.out.println("LinkedList: " + animals);

animals.addFirst("Dog");
System.out.println("LinkedList after addFirst(): " + animals);

// add elements at the end
animals.addLast("Zebra");
System.out.println("LinkedList after addLast(): " + animals);

// remove the first element
animals.removeFirst();
System.out.println("LinkedList after removeFirst(): " + animals);

// remove the last element
animals.removeLast();
System.out.println("LinkedList after removeLast(): " + animals);
}
}

输出:

1
2
3
4
5
LinkedList: [Cow]
LinkedList after addFirst(): [Dog, Cow]
LinkedList after addLast(): [Dog, Cow, Zebra]
LinkedList after removeFirst(): [Cow, Zebra]
LinkedList after removeLast(): [Cow]

遍历 LinkedList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.LinkedList;

class Main {
public static void main(String[] args) {
// Creating a linked list
LinkedList<String> animals = new LinkedList<>();
animals.add("Cow");
animals.add("Cat");
animals.add("Dog");
System.out.println("LinkedList: " + animals);

// Using forEach loop
System.out.println("Accessing linked list elements:");
for(String animal: animals) {
System.out.print(animal);
System.out.print(", ");
}
}
}

输出:

1
2
3
LinkedList: [Cow, Cat, Dog]
Accessing linked list elements:
Cow, Cat, Dog,

LinkedList Vs. ArrayList

Java ArrayListLinkedList都实现Collections框架的List接口。但是,它们之间存在一些差异。

LinkedList ArrayList
实现ListQueueDeque接口。 实现List接口
一个单位会存三个值 一个单位存一个值
提供双向链表实现 提供可调整大小的数组实现
每当添加元素时,上一个和下一个地址都会更改 每当添加元素时,该位置之后的所有元素都会移动
要访问元素,我们需要从头开始迭代到元素 可以使用索引随机访问元素

在Java中我们可以通过接口创建LinkedList

1
2
3
4
5
6
7
8
// create linkedlist using List
List<String> animals1 = new LinkedList<>();

// creating linkedlist using Queue
Queue<String> animals2 = new LinkedList<>();

// creating linkedlist using Deque
Deque<String> animals3 = new LinkedList<>();

在这里,如果LinkedList是使用一个接口创建的,则我们不能使用其他接口提供的方法。也就是说,animals1不能使用特定于QueueDeque接口的方法。

ArrayDeque

在Java中,我们可以使用ArrayDeque类使用数组来实现队列和双端队列数据结构。

ArrayDeque实现了QueueDeque接口

创建 ArrayDeque

为了创建数组双端队列,我们必须导入java.util.ArrayDeque包。

1
ArrayDeque<Type> animal = new ArrayDeque<>();

在此,Type表示数组双端队列的类型。

1
2
3
4
5
// Creating String type ArrayDeque
ArrayDeque<String> animals = new ArrayDeque<>();

// Creating Integer type ArrayDeque
ArrayDeque<Integer> age = new ArrayDeque<>();

ArrayDeque 中的方法

ArrayDeque类为QueueDeque接口中存在的所有方法提供实现。

Deque插入元素

添加元素通过 add()addFirst()addLast()
  • add() - 在数组双端队列的末尾插入指定的元素
  • addFirst() - 在数组双端队列的开始处插入指定的元素
  • addLast() - 在数组双端队列的末尾插入指定的

注意: 如果数组双端队列已满,则所有这些方法add(),addFirst()和addLast()都会引发IllegalStateException。

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();

// Using add()
animals.add("Dog");

// Using addFirst()
animals.addFirst("Cat");

// Using addLast()
animals.addLast("Horse");
System.out.println("ArrayDeque: " + animals);
}
}

输出:

1
ArrayDeque: [Cat, Dog, Horse]
插入数据offer()offerFirst()offerLast()
  • offer() - 在数组双端队列的末尾插入指定的元素
  • offerFirst() - 在数组双端队列的开始处插入指定的元素
  • offerLast() - 在数组双端队列的末尾插入指定的元素

注意: 如果成功插入元素,则offer(),offerFirst()和offerLast()返回true;否则,返回true。如果数组双端队列已满,则这些方法将返回false。

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
// Using offer()
animals.offer("Dog");

// Using offerFirst()
animals.offerFirst("Cat");

// Using offerLast()
animals.offerLast("Horse");
System.out.println("ArrayDeque: " + animals);
}
}

输出:

1
ArrayDeque: [Cat, Dog, Horse]

注意: 如果阵列双端队列已满

  • add()方法将引发异常
  • offer()方法返回false

获取ArrayDeque元素

获取元素getFirst()getLast()
  • getFirst() - 返回数组双端队列的第一个元素
  • getLast() - 返回数组双端队列的最后一个元素

注意: 如果数组双端队列为空,则getFirst()getLast()引发NoSuchElementException

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayDeque: " + animals);

// Get the first element
String firstElement = animals.getFirst();
System.out.println("First Element: " + firstElement);

// Get the last element
String lastElement = animals.getLast();
System.out.println("Last Element: " + lastElement);
}
}

输出:

1
2
3
ArrayDeque: [Dog, Cat, Horse]
First Element: Dog
Last Element: Horse
使用peek()peekFirst()peekLast()方法获取元素
  • peek() - 返回数组双端队列的第一个元素
  • peekFirst() - 返回数组双端队列的第一个元素(与peek()等效)
  • peekLast()-返回数组双端队列的最后一个元素

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayDeque: " + animals);

// Using peek()
String element = animals.peek();
System.out.println("Head Element: " + element);

// Using peekFirst()
String firstElement = animals.peekFirst();
System.out.println("First Element: " + firstElement);

// Using peekLast
String lastElement = animals.peekLast();
System.out.println("Last Element: " + lastElement);
}
}

输出:

1
2
3
4
ArrayDeque: [Dog, Cat, Horse]
Head Element: Dog
First Element: Dog
Last Element: Horse

注意: 如果数组双端队列为空,则peek()peekFirst()getLast()会引发NoSuchElementException

移除ArrayDeque中的元素

移除元素remove()removeFirst()removeLast()
  • remove() - 返回并从数组双端队列的第一个元素中删除一个元素.
  • removeFirst() - 返回并从数组双端队列中删除第一个元素(与remove()等效)
  • remove(element) - 返回并从数组双端队列的头部移除指定的元素
  • removeLast() - 返回并从数组双端队列中删除最后一个元素

注意: 如果数组双端队列为空,则remove()removeFirst()removeLast()方法将引发异常。另外,如果未找到元素,则remove(element)会引发异常。

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
animals.add("Horse");
System.out.println("ArrayDeque: " + animals);

// Using remove()
String element = animals.remove();
System.out.println("Removed Element: " + element);

System.out.println("New ArrayDeque: " + animals);

// Using removeFirst()
String firstElement = animals.removeFirst();
System.out.println("Removed First Element: " + firstElement);

// Using removeLast()
String lastElement = animals.removeLast();
System.out.println("Removed Last Element: " + lastElement);
}
}

输出:

1
2
3
4
5
ArrayDeque: [Dog, Cat, Cow, Horse]
Removed Element: Dog
New ArrayDeque: [Cat, Cow, Horse]
Removed First Element: Cat
Removed Last Element: Horse
移除元素poll()pollFirst()pollLast()方法
  • poll() - 返回并删除数组双端队列的第一个元素
  • pollFirst() - 返回并删除数组双端队列的第一个元素(与poll()等效)
  • pollLast() - 返回并删除数组双端队列的最后一个元素

注意: 如果数组双端队列为空,则如果找不到该元素,则poll()pollFirst()pollLast()返回null。

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
animals.add("Horse");
System.out.println("ArrayDeque: " + animals);

// Using poll()
String element = animals.poll();
System.out.println("Removed Element: " + element);
System.out.println("New ArrayDeque: " + animals);

// Using pollFirst()
String firstElement = animals.pollFirst();
System.out.println("Removed First Element: " + firstElement);

// Using pollLast()
String lastElement = animals.pollLast();
System.out.println("Removed Last Element: " + lastElement);
}
}

输出:

1
2
3
4
5
ArrayDeque: [Dog, Cat, Cow, Horse]
Removed Element: Dog
New ArrayDeque: [Cat, Cow, Horse]
Removed First Element: Cat
Removed Last Element: Horse
移除所有元素clear()

要从数组双端队列中删除所有元素,我们使用clear()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayDeque: " + animals);

// Using clear()
animals.clear();

System.out.println("New ArrayDeque: " + animals);
}
}

输出:

1
2
ArrayDeque: [Dog, Cat, Horse]
New ArrayDeque: []

遍历 ArrayDeque

  • iterator() - 返回一个迭代器,该迭代器可用于遍历数组双端队列
  • descendingIterator() - 返回一个迭代器,该迭代器可用于以相反顺序遍历数组双端队列

为了使用这些方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.ArrayDeque;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
ArrayDeque<String> animals= new ArrayDeque<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");

System.out.print("ArrayDeque: ");

// Using iterator()
Iterator<String> iterate = animals.iterator();
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}

System.out.print("\nArrayDeque in reverse order: ");
// Using descendingIterator()
Iterator<String> desIterate = animals.descendingIterator();
while(desIterate.hasNext()) {
System.out.print(desIterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
ArrayDeque: [Dog, Cat, Horse]
ArrayDeque in reverse order: [Horse, Cat, Dog]

其他方法

Methods Descriptions
element() 从数组双端队列的头部返回一个元素。
contains(element) 在数组双端队列中搜索指定的元素。如果找到该元素,则返回true,否则返回false。
size() 返回数组双端队列的长度。
toArray() 将数组双端队列转换为数组并返回。
clone() 创建数组双端队列的副本并返回它。

ArrayDeque作为栈(Stack)

要在Java中实现LIFO(后进先出)堆栈,建议使用dequeArrayDeque会比Stack更快些.

ArrayDeque提供了以下可用于实现stack的方法。

  • push - 添加一个元素到stack顶部
  • peek -返回stack顶部的元素
  • pop()- 移除并返回stack顶部的元素

例子🌰:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayDeque;

class Main {
public static void main(String[] args) {
ArrayDeque<String> stack = new ArrayDeque<>();

// Add elements to stack
stack.push("Dog");
stack.push("Cat");
stack.push("Horse");
System.out.println("Stack: " + stack);

// Access element from top of stack
String element = stack.peek();
System.out.println("Accessed Element: " + element);

// Remove elements from top of stack
String remElement = stack.pop();
System.out.println("Removed element: " + remElement);
}
}

输出:

1
2
3
Stack: [Horse, Cat, Dog]
Accessed Element: Horse
Removed Element: Horse

ArrayDequeVsLinkedList Class

ArrayDequeJava LinkedList均实现Deque接口。但是他们存在一些差别

  • LinkedList 支持null元素,但是ArrayDeque不支持
  • 链表中的每个节点都包含指向其他节点的链接。这就是为什么LinkedListArrayDeque需要更多存储的原因。
  • 如果要实现队列或双端队列数据结构,ArrayDeque可能比LinkedList更快。

BlockingQueue

BlockingQueue接口扩展了Queue接口.它允许任何操作等待成功执行。

例如,如果我们要从空队列中删除元素,则blcoking queue允许删除操作等待,直到队列中包含一些要删除的元素。

实现BlockingQueue

由于BlockingQueue是一个接口,因此我们无法提供它的直接实现。为了使用BlockingQueue的功能,我们需要使用实现它的类。

如何使用blocking queues

为了使用BlockingQueue,我们必须导入java.util.concurrent.BlockingQueue包。

1
2
3
4
5
// Array implementation of BlockingQueue
BlockingQueue<String> animal1 = new ArraryBlockingQueue<>();

// LinkedList implementation of BlockingQueue
BlockingQueue<String> animal2 = new LinkedBlockingQueue<>();

在这里,我们分别创建了类ArrayBlockingQueueLinkedBlockingQueue的对象animal1animal2。这些对象可以使用BlockingQueue接口的功能。

BlockingQueue方法

根据队列是满还是空,阻塞队列的方法可以分为3类:

这些方法会抛出异常

  • add() - 将元素插入到队列末尾的blocking queue队列中。如果队列以满,则抛出异常
  • element() - 返回blocking queue头部元素.如果队列为空则抛出异常
  • remove() - 从blocking queue移除元素.如果队列为空则抛出异常.

返回一些值的方法

  • offer() - 将元素插入到blocking queue队列的尾部.如果队列已满,则返回false.
  • peek() - 返回blocking queue队列头部元素.如果队列为空则返回null.
  • poll() - 从blocking queue队列删除一个元素. 如果队列为空,则返回null.
offer()poll()更多信息

offer()poll()方法可以设定时间。也就是说,我们可以传递时间单位作为参数。例如:

1
offer(value, 100, milliseconds)
  • value - 需要插入到队列的数据
  • 100-延迟时间
  • milliseconds - 时间单位

这意味着offer()方法将尝试将元素插入block queue用100毫秒。如果无法在100毫秒内插入元素,则该方法返回false

注意: 除了milliseconds我们还可以配置:days,hours,minutes,seconds,microseconds,nanoseconds用于offer()poll()方法.

blocks中的操作符

BlockingQueue提供了等待操作队列方法,如果队列为空或者已满.

  • put() - 将元素插入到blocking queue。如果队列已满,它将等待直到队列有空间插入元素。
  • take() - 从blocking queue移除第一个元素并返回一个元素.如果队列为空,则等待队列有元素再删除.

假设我们想将元素插入队列。如果队列已满,则put()方法将等待,直到队列有空间插入元素。

同样,如果我们要从队列中删除元素。如果队列为空,则take()方法将等待直到队列包含要删除的元素。

ArrayBlockingQueue实现BlockingQueue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;

class Main {

public static void main(String[] args) {
// Create a blocking queue using the ArrayBlockingQueue
BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(5);

try {
// Insert element to blocking queue
numbers.put(2);
numbers.put(1);
numbers.put(3);
System.out.println("BLockingQueue: " + numbers);

// Remove Elements from blocking queue
int removedNumber = numbers.take();
System.out.println("Removed Number: " + removedNumber);
}

catch(Exception e) {
e.getStackTrace();
}
}
}

输出:

1
2
BlockingQueue: [2, 1, 3]
Removed Element: 2

为什么使用BlockingQueue

在Java中,BlockingQueue被视为线程安全的集合。这是因为它在多线程操作中可能会有所帮助。

假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。

现在,如果第一个线程运行较慢,则阻塞队列可使第二个线程等待,直到第一个线程完成其操作。

ArrayBlockingQueue

ArrayBlockingQueue实现了Java Collections框架中blocking queue接口通过数组.

创建ArrayBlockingQueue

创建一个数组blocking queue,我们必须导入java.util.concurrent.ArrayBlockingQueue包.

导入包后,可以使用以下方法在Java中创建数组blocking queue

1
ArrayBlockingQueue<Type> animal = new ArrayBlockingQueue<>(int capacity);
  • Type - array blocking queue的类型
  • capacity - 这个 array blocking queue大小
1
2
3
4
5
// Creating String type ArrayBlockingQueue with size 5
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

// Creating Integer type ArrayBlockingQueue with size 5
ArrayBlockingQueue<Integer> age = new ArrayBlockingQueue<>(5);

注意: 必须提供数组的大小.

ArrayBlockingQueue中方法

ArrayBlockingQueue类提供BlockingQueue接口中所有方法的实现。

这些方法用于从数组blocking queue中插入,访问和删除元素。

put()take()方法支持blocking操作在array blocking queue.

这个两个方法会和array blocking queue其他类型队列有区别.

插入元素

  • add() - 将指定的元素插入到array blocking queue.如果队列满了则抛出异常.
  • offer() - 将指定的元素插入到array blocking queue.如果队列满了则返回false.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.concurrent.ArrayBlockingQueue;

class Main {
public static void main(String[] args) {
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

// Using add()
animals.add("Dog");
animals.add("Cat");

// Using offer()
animals.offer("Horse");
System.out.println("ArrayBlockingQueue: " + animals);
}
}

输出:

1
ArrayBlockingQueue: [Dog, Cat, Horse]

获取元素

  • peek() - 从array blocking queue头部返回一个元素.如果队列是空则返回null
  • iterator() - 返回一个迭代器对象,以顺序访问array blocking queue中的元素。如果队列为空,则抛出异常。我们必须导入java.util.Iterator包才能使用它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.concurrent.ArrayBlockingQueue;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

// Add elements
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayBlockingQueue: " + animals);

// Using peek()
String element = animals.peek();
System.out.println("Accessed Element: " + element);

// Using iterator()
Iterator<String> iterate = animals.iterator();
System.out.print("ArrayBlockingQueue Elements: ");

while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
3
ArrayBlockingQueue: [Dog, Cat, Horse]
Accessed Element: Dog
ArrayBlockingQueue Elements: Dog, Cat, Horse,

移除元素

  • remove() - 移除并返回删除的制定元素从array blocking queue.如果队列为空则抛出异常.
  • poll() - 移除并返回删除的制定元素从array blocking queue.如果队列为空则返回null
  • clear() - 从array block queue所有元素.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.concurrent.ArrayBlockingQueue;

class Main {
public static void main(String[] args) {
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("ArrayBlockingQueue: " + animals);

// Using remove()
String element1 = animals.remove();
System.out.println("Removed Element:");
System.out.println("Using remove(): " + element1);

// Using poll()
String element2 = animals.poll();
System.out.println("Using poll(): " + element2);

// Using clear()
animals.clear();
System.out.println("Updated ArrayBlockingQueue: " + animals);
}
}

输入:

1
2
3
4
5
ArrayBlockingQueue: [Dog, Cat, Horse]
Removed Elements:
Using remove(): Dog
Using poll(): Cat
Updated ArrayBlockingQueue: []

put()take()方法

在多线程处理中,我们可以使用put()take()阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。

put()方法

将元素添加到array blocking queue尾部.

如果array blocking queue已满,它将等待,直到array blocking queue中有空间可添加元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.concurrent.ArrayBlockingQueue;

class Main {
public static void main(String[] args) {
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

try {
// Add elements to animals
animals.put("Dog");
animals.put("Cat");
System.out.println("ArrayBlockingQueue: " + animals);
}
catch(Exception e) {
System.out.println(e);
}
}
}

输出:

1
ArrayBlockingQueue: [Dog, Cat]

在这里,如果put()方法在等待时被中断,则可能会抛出InterruptedException。因此,我们必须将其包含在try..catch块中。

take()方法

删除array blocking queue中头部元素,并返回.

如果array blocking queue为空, 则等到array blocking queue有元素可以删除.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.concurrent.ArrayBlockingQueue;

class Main {
public static void main(String[] args) {
ArrayBlockingQueue<String> animals = new ArrayBlockingQueue<>(5);

try {
//Add elements to animals
animals.put("Dog");
animals.put("Cat");
System.out.println("ArrayBlockingQueue: " + animals);

// Remove an element
String element = animals.take();
System.out.println("Removed Element: " + element);
}
catch(Exception e) {
System.out.println(e);
}
}
}

输出:

1
2
ArrayBlockingQueue: [Dog, Cat]
Removed Element: Dog

在这里,如果take()方法在等待时被中断,则会抛出InterrupedException。因此,我们必须将其封闭在try ... catch块中。

其它方法

Methods Descriptions
contains(element) array blocking queue搜索指定的元素.如果找到元素就返回true,没有找到则返回false.
size() 返回数组的长度
toArray() 转换array blocking queue为数组
toString() 转换array blocking queue为字符串

为啥使用ArrayBlockingQueue

ArrayBlockingQueue使用数组作为其内部存储。

它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。

假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。

现在,如果第一个线程比第二个线程慢,那么数组阻塞队列可以使第二个线程等待,直到第一个线程完成其操作。

LinkedBlockingQueue

Java Collections框架中的LinkedBlockingQueue实现了阻塞队列,实现了linked list接口.

创建LinkedBlockingQueue

为了创建linked blocking queue我们必须导入java.util.concurrent.LinkedBlockingQueue包.

不指定大小

1
LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>();

此处的默认初始容量为231-1。

指定大小

1
LinkedBlockingQueue<Type> animal = new LinkedBlockingQueue<>(int capacity);
  • Type - linked blocking queue的类型
  • capacity - linked blocking queue的大小
1
2
3
4
5
// Creating String type LinkedBlockingQueue with size 5
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

// Creating Integer type LinkedBlockingQueue with size 5
LinkedBlockingQueue<Integer> age = new LinkedBlockingQueue<>(5);

注意:不必提供链接列表的大小。

LinkedBlockingQueue中的方法

LinkedBlockingQueue类提供BlockingQueue接口中所有方法的实现。

这些方法提供了LinkedBlockingQueue中插入,获取,删除元素的方法.

另外,我们还将学习支持LinkedBlockingQueue中的阻塞操作的两种方法put()take()

这两种方法将LinkedBlockingQueue与其他典型队列区分开来。

插入元素

  • add() - 将指定的元素插入到LinkedBlockingQueue中. 如果队列满了则它会抛出异常.
  • offer() - 将指定的元素插入到LinkedBlockingQueue中.如果队列满了则它会返回false.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.concurrent.LinkedBlockingQueue;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

// Using add()
animals.add("Dog");
animals.add("Cat");

// Using offer()
animals.offer("Horse");
System.out.println("LinkedBlockingQueue: " + animals);
}
}

输出:

1
LinkedBlockingQueue: [Dog, Cat, Horse]

获取元素

  • peek() - 将LinkedBlockingQueue中的第一个元素返回.如果队列为空,则返回null
  • iterator - 返回LinkedBlockQueue元素的迭代器.如果队列为空则它会抛出一个错误.使用它我们需要引入java.util.Iterator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.concurrent.LinkedBlockingQueue;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

// Add elements
animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("LinkedBlockingQueue: " + animals);

// Using peek()
String element = animals.peek();
System.out.println("Accessed Element: " + element);

// Using iterator()
Iterator<String> iterate = animals.iterator();
System.out.print("LinkedBlockingQueue Elements: ");

while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
3
LinkedBlockingQueue: [Dog, Cat, Horse]
Accessed Element: Dog
LinkedBlockingQueue Elements: Dog, Cat, Horse,

移除元素

  • remove() - 返回并LinkedBlockingQueue中删除指定的元素。当前队列如果为空则抛出异常.
  • poll() - 删除并返回LinkedBlockQueue的元素.如果队列为空则返回null.
  • clear() - 移除LinkedBlockQueue中的所有元素.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.concurrent.LinkedBlockingQueue;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

animals.add("Dog");
animals.add("Cat");
animals.add("Horse");
System.out.println("LinkedBlockingQueue " + animals);

// Using remove()
String element1 = animals.remove();
System.out.println("Removed Element:");
System.out.println("Using remove(): " + element1);

// Using poll()
String element2 = animals.poll();
System.out.println("Using poll(): " + element2);

// Using clear()
animals.clear();
System.out.println("Updated LinkedBlockingQueue " + animals);
}
}

输出:

1
2
3
4
5
LinkedBlockingQueue: [Dog, Cat, Horse]
Removed Elements:
Using remove(): Dog
Using poll(): Cat
Updated LinkedBlockingQueue: []

put()take()方法

在多线程处理中,我们可以使用put()take()阻止一个线程的操作,以使其与另一个线程同步。这些方法将等待,直到可以成功执行。

put()方法

要将指定的元素插入到LinkedBlockingQueue的末尾,我们使用put()方法。

如果链接的队列已满,它将等待,直到链接的队列中有足够的空间来插入元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.concurrent.LinkedBlockingQueue;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

try {
// Add elements to animals
animals.put("Dog");
animals.put("Cat");
System.out.println("LinkedBlockingQueue: " + animals);
}
catch(Exception e) {
System.out.println(e);
}
}
}

输出:

1
LinkedBlockingQueue: [Dog, Cat]

在这里,如果put()方法在等待时被中断,则可能会抛出InterruptedException

take()方法

移除并返回LinkedBlockingQueue头部元素.

如果LinkedBlockingQueue为空,它会等待LinkedBlockingQueue存在元素并将它删除.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.concurrent.LinkedBlockingQueue;

class Main {
public static void main(String[] args) {
LinkedBlockingQueue<String> animals = new LinkedBlockingQueue<>(5);

try {
//Add elements to animals
animals.put("Dog");
animals.put("Cat");
System.out.println("LinkedBlockingQueue: " + animals);

// Remove an element
String element = animals.take();
System.out.println("Removed Element: " + element);
System.out.println("New LinkedBlockingQueue: " + animals);
}
catch(Exception e) {
System.out.println(e);
}
}
}

输出:

1
2
3
LinkedBlockingQueue: [Dog, Cat]
Removed Element: Dog
New LinkedBlockingQueue: [Cat]

在这里,如果take()方法在等待时被中断,则会抛出InterrupedException。因此,我们必须将其封闭在try ... catch块中。

其它方法

Methods Descriptions
contains(element) LinkedBlockingQueue搜索是否存在指定元素 . 如果找到则返回true,否则返回false.
size() 返回LinkedBlockingQueue的大小
toArray() LinkedBlockingQueue转换成数组
toString() LinkedBlockingQueue转换成字符串

为什么使用LinkedBlockingQueue

LinkedBlockingQueue使用链接列表作为其内部存储。

它被认为是线程安全的集合。因此,它通常用于多线程应用程序中。

假设一个线程正在将元素插入队列,而另一个线程正在从队列中删除元素。

现在,如果第一个线程比第二个线程慢,然后LinkedBlockingQueue可以使第二个线程等待,直到第一个线程完成其操作。

##Map 接口

Java collections frameworkMap接口提供了map数据结构的功能。

Working of Map

Java中,元素在Map中以key/value形式保存着。Keys是与Values关联的唯一值。

一个map中不会包含重复的keys,每一个key都有关联的唯一一个value

我们可以使用与它们关联的键来访问和修改值。

在上图中,key/value有:us/United Statesbr/Braziles/Spain.

我们可以使用它们的对应键访问这些值。

注意: Map界面维护3个不同的集合:

  1. keys集合
  2. values集合
  3. key/value关联值集合

我们可以分别访问:keysvalueskey/value

实现Map

由于Mapinterface,因此我们无法从中创建对象。

为了使用Map接口的功能,我们可以使用以下类:

这些类在集合框架中定义并实现Map接口。

扩展 Map 接口

这些子接口还扩展了Map接口:

怎样使用 Map

在Java中,必须导入java.util.Map包才能使用Map

1
2
// Map implementation using HashMap
Map<Key, Value> numbers = new HashMap<>();

在上面的代码中,我们创建了一个名为numbersMap。我们已经使用HashMap类来实现Map接口。

  • Key - 用于关联map中每个元素(值)的唯一标识符.
  • Value - mapkey关联的元素

Map 中常用方法

Map接口包含Collection接口的所有方法。这是因为CollectionMap的超级接口。

除了Collection中可用的方法外,Map还包括以下方法:

  • put(K, V) - 将key-Kvalue-V插入到map中,如果key已经存在,则V替换旧值
  • putAll()- 将指定map中所有内容插入到当前map
  • putIfAbsent(K, V) - 如果KV并没有关联,则将它们插入到map
  • get(K) - 返回与指定keyK关联的值。如果找不到该K,则返回null
  • getOrDefault(K, defaultValue) - 返回与指定keyK关联的值,如果key不存在,则返回defaultValue
  • containsKey(K) - 检查map中是否存在指定的keyK
  • containsValue(V) - 检查map中是否存在指定的valueV
  • replace(K,V) - 用新的valueV替换,keyK中旧的value
  • replace(K, oldValue, newValue) - 仅当keyK与valueoldValue关联时,才用新valuenewValue替换keyK的值
  • remove(K) - 从map中删除key是K中的数据
  • remove(K, V) - 从map中删除key是K,value是V的数据
  • keySet() - 返回map中所有key的集合
  • values() - 返回map中所有value的集合
  • entrySet() - 返回mapkey/value集合

实现Map接口

HashMap 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.Map;
import java.util.HashMap;

class Main {

public static void main(String[] args) {
// Creating a map using the HashMap
Map<String, Integer> numbers = new HashMap<>();

// Insert elements to the map
numbers.put("One", 1);
numbers.put("Two", 2);
System.out.println("Map: " + numbers);

// Access keys of the map
System.out.println("Keys: " + numbers.keySet());

// Access values of the map
System.out.println("Values: " + numbers.values());

// Access entries of the map
System.out.println("Entries: " + numbers.entrySet());

// Remove Elements from the map
int value = numbers.remove("Two");
System.out.println("Removed Value: " + value);
}
}

输出:

1
2
3
4
5
Map: {One=1, Two=2}
Keys: [One, Two]
Values: [1, 2]
Entries: [One=1, Two=2]
Removed Value: 2

TreeMap 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Map;
import java.util.TreeMap;

class Main {

public static void main(String[] args) {
// Creating Map using TreeMap
Map<String, Integer> values = new TreeMap<>();

// Insert elements to map
values.put("Second", 2);
values.put("First", 1);
System.out.println("Map using TreeMap: " + values);

// Replacing the values
values.replace("First", 11);
values.replace("Second", 22);
System.out.println("New Map: " + values);

// Remove elements from the map
int removedValue = values.remove("First");
System.out.println("Removed Value: " + removedValue);
}
}

输出:

1
2
3
Map using TreeMap: {First=1, Second=2}
New Map: {First=11, Second=22}
Removed Value: 11

HashMap

Java collections frameworkHashMap类提供了 哈希表数据结构功能

它将元素存储在key/value对中。此处,key是用于关联map上每个value的唯一标识符。

HashMap类实现Map接口

创建 HashMap

为了创建HashMap,我们必须首先导入java.util.HashMap包。导入包后,就可以使用Java创建HashMap

1
2
// hashMap creation with 8 capacity and 0.6 load factor
HashMap<K, V> numbers = new HashMap<>();

在上面代码中,我们创建了名为numbers的hashmap.K代表key,V代表value.

1
HashMap<String, Integer> numbers = new HashMap<>();

上面例子中keys类型是String,values类型是Integer.

例子🌰 创建HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.HashMap;

class Main {
public static void main(String[] args) {

// create a hashmap
HashMap<String, Integer> languages = new HashMap<>();

// add elements to hashmap
languages.put("Java", 8);
languages.put("JavaScript", 1);
languages.put("Python", 3);
System.out.println("HashMap: " + languages);
}
}

输出:

1
HashMap: {Java=8, JavaScript=1, Python=3}

上面例子中我们创建了名为languages的HashMap.我们用put(k,v)map中添加元素。

Java中HashMap 基本操作

HashMap中基本操作分为四种:

  • 添加元素
  • 获取元素
  • 修改元素
  • 删除元素

HashMap 中新增元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.HashMap;

class Main {
public static void main(String[] args) {

// create a hashmap
HashMap<String, Integer> numbers = new HashMap<>();

System.out.println("Initial HashMap: " + numbers);
// put() method to add elements
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("HashMap after put(): " + numbers);
}
}

输出:

1
2
Initial HashMap: {}
HashMap after put(): {One=1, Two=2, Three=3}

在上面的示例中,我们创建了一个名为number的HashMap。在这里,我们使用了put()方法将元素添加到数字中。

其他添加元素方法:

获取一个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.HashMap;

class Main {
public static void main(String[] args) {

HashMap<Integer, String> languages = new HashMap<>();
languages.put(1, "Java");
languages.put(2, "Python");
languages.put(3, "JavaScript");
System.out.println("HashMap: " + languages);

// get() method to get value
String value = languages.get(1);
System.out.println("Value at index 1: " + value);
}
}

输出:

1
2
HashMap: {1=Java, 2=Python, 3=JavaScript}
Value at index 1: Java

上面例子中:

1
languages.get(1);

在这里,get()方法将key作为其参数,并返回与key关联的相应value

通过keySet()values()entrySet()获取keysvalueskey/value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.HashMap;

class Main {
public static void main(String[] args) {
HashMap<Integer, String> languages = new HashMap<>();

languages.put(1, "Java");
languages.put(2, "Python");
languages.put(3, "JavaScript");
System.out.println("HashMap: " + languages);

// return set view of keys
// using keySet()
System.out.println("Keys: " + languages.keySet());

// return set view of values
// using values()
System.out.println("Values: " + languages.values());

// return set view of key/value pairs
// using entrySet()
System.out.println("Key/Value mappings: " + languages.entrySet());
}
}

输出:

1
2
3
4
HashMap: {1=Java, 2=Python, 3=JavaScript}
Keys: [1, 2, 3]
Values: [Java, Python, JavaScript]
Key/Value mappings: [1=Java, 2=Python, 3=JavaScript]

其他获取数据方法:

改变 HashMap值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.HashMap;

class Main {
public static void main(String[] args) {

HashMap<Integer, String> languages = new HashMap<>();
languages.put(1, "Java");
languages.put(2, "Python");
languages.put(3, "JavaScript");
System.out.println("Original HashMap: " + languages);

// change element with key 2
languages.replace(2, "C++");
System.out.println("HashMap using replace(): " + languages);
}
}

输出:

1
2
Original HashMap: {1=Java, 2=Python, 3=JavaScript}
HashMap using replace(): {1=Java, 2=C++, 3=JavaScript}

将key是2的值替换成了C++.

其他修改值方法:

移除HashMap元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.HashMap;

class Main {
public static void main(String[] args) {

HashMap<Integer, String> languages = new HashMap<>();
languages.put(1, "Java");
languages.put(2, "Python");
languages.put(3, "JavaScript");
System.out.println("HashMap: " + languages);

// remove element associated with key 2
String value = languages.remove(2);
System.out.println("Removed value: " + value);

System.out.println("Updated HashMap: " + languages);
}
}

输出:

1
2
3
HashMap: {1=Java, 2=Python, 3=JavaScript}
Removed value: Python
Updated HashMap: {1=Java, 3=JavaScript}

在这里,remove()方法将key作为其参数。然后,它返回与key关联的value并删除条目。

也可以在某中条件下删除数据

1
remove(2,'C++');

在此,只有key2与valueC ++关联时,remove()方法才会删除该条目。由于2C ++没有关联,因此它不会删除该条目。

其他 HashMap方法

Method Description
clear() HashMap删除所有映射
compute() 计算指定key的新值
computeIfAbsent() 如果不存在key的映射,则计算value
computeIfPresent() 如果存在key,则计算要映射的value
merge() 将指定的映射合并到HashMap
clone() 制作HashMap的副本
containsKey() 检测key是否在HashMap中存在
containsValue() 检测value是否在HashMap中存在
size() 返回HashMap中的大小
isEmpty() 检测HashMap是否为空

遍历 HashMap

遍历HashMap可以通过Java for-each loop.我们可以遍历:keysvalueskey/value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.HashMap;
import java.util.Map.Entry;

class Main {
public static void main(String[] args) {

// create a HashMap
HashMap<Integer, String> languages = new HashMap<>();
languages.put(1, "Java");
languages.put(2, "Python");
languages.put(3, "JavaScript");
System.out.println("HashMap: " + languages);

// iterate through keys only
System.out.print("Keys: ");
for (Integer key : languages.keySet()) {
System.out.print(key);
System.out.print(", ");
}

// iterate through values only
System.out.print("\nValues: ");
for (String value : languages.values()) {
System.out.print(value);
System.out.print(", ");
}

// iterate through key/value entries
System.out.print("\nEntries: ");
for (Entry<Integer, String> entry : languages.entrySet()) {
System.out.print(entry);
System.out.print(", ");
}
}
}

输出:

1
2
3
4
HashMap: {1=Java, 2=Python, 3=JavaScript}
Keys: 1, 2, 3,
Values: Java, Python, JavaScript,
Entries: 1=Java, 2=Python, 3=JavaScript,

请注意,我们在上面的示例中使用了Map.Entry.这是Map接口的嵌套类,该类返回map的视图(元素)。

为了使用此类,我们首先需要导入java.util.Map.Entry包。

从其它Map 创建HashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.HashMap;
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

// create a treemap
TreeMap<String, Integer> evenNumbers = new TreeMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("TreeMap: " + evenNumbers);

// create hashmap from the treemap
HashMap<String, Integer> numbers = new HashMap<>(evenNumbers);
numbers.put("Three", 3);
System.out.println("HashMap: " + numbers);
}
}

输出:

1
2
TreeMap: {Four=4, Two=2}
HashMap: {Two=2, Three=3, Four=4}

在上面的示例中,我们创建了一个名为evenNumbersTreeMap。注意表达式:

1
numbers = new HashMap<>(evenNumbers)

在这里,我们使用TreeMap创建一个名为numberHashMap

注意:创建HashMap时,我们可以包括可选参数:容量和负载系数。

1
HashMap<K, V> numbers = new HashMap<>(8, 0.6f);
  • 8(容量是 8) - 这意味着它可以存储8个条目。
  • 0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.

如果未使用可选参数,则默认容量为16,默认负载系数为0.75。

LinkedHashMap

Javacollections frameworkLinkedHashMap类提供了Map接口的哈希表和链表实现。

LinkedHashMap接口扩展了HashMap类,以将其条目存储在哈希表中。它在内部维护所有条目之间的双向链接列表,以对条目进行排序。

创建 LinkedHashMap

为了创建LinkedHashMap,我们必须首先导入java.util.LinkedHashMap包。

1
2
// LinkedHashMap with initial capacity 8 and load factor 0.6
LinkedHashMap<Key, Value> numbers = new LinkedHashMap<>(8, 0.6f);

在上面的代码中,我们创建了一个名为NumbersLinkedHashMap

  • Key - 用于关联map中每个元素(value)的唯一标识符
  • Value - map中按key所关联的元素

注意新的LinkedHashMap <>(8,0.6)部分。在这里,第一个参数是容量,第二个参数是负载系数。

  • 8(容量是 8) - 这意味着它可以存储8个条目。
  • 0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.

如果未使用可选参数,则默认容量为16,默认负载系数为0.75。

注意: LinkedHashMap类还允许我们定义其条目的顺序。例如

1
2
// LinkedHashMap with specified order
LinkedHashMap<Key, Value> numbers2 = new LinkedHashMap<>(capacity, loadFactor, accessOrder);

在这里,accessOrder是一个布尔值。其默认值为false。在这种情况下,链接的哈希图中的条目将根据其插入顺序进行排序。

如果accessOrdertrue,LinkedHashMap中的条目将按从最近访问的顺序排列。

创建 LinkedHashMap 从另外一个 Map

创建一个包含其他map所有元素的LinkedHashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {
// Creating a LinkedHashMap of even numbers
LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("LinkedHashMap1: " + evenNumbers);

// Creating a LinkedHashMap from other LinkedHashMap
LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>(evenNumbers);
numbers.put("Three", 3);
System.out.println("LinkedHashMap2: " + numbers);
}
}

输出:

1
2
LinkedHashMap1: {Two=2, Four=4}
LinkedHashMap2: {Two=2, Four=4, Three=3}

LinkedHashMap中的方法

插入元素

  • put() - 将指定的key/value映射插入到映射中
  • putAll() -将指定map中的所有条目插入此map中
  • putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入到map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {
// Creating LinkedHashMap of even numbers
LinkedHashMap<String, Integer> evenNumbers = new LinkedHashMap<>();

// Using put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("Original LinkedHashMap: " + evenNumbers);

// Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("Updated LinkedHashMap(): " + evenNumbers);

//Creating LinkedHashMap of numbers
LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>();
numbers.put("One", 1);

// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("New LinkedHashMap: " + numbers);
}
}

输出:

1
2
3
Original LinkedHashMap: {Two=2, Four=4}
Updated LinkedHashMap: {Two=2, Four=4, Six=6}
New LinkedHashMap: {One=1, Two=2, Four=4, Six=6}

获取元素

  • entrySet() - 获取map中key/value的集合
  • keySet() - 获取mapkeys的集合
  • values() - 获取mapvalues的集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {
LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>();

numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("LinkedHashMap: " + numbers);

// Using entrySet()
System.out.println("Key/Value mappings: " + numbers.entrySet());

// Using keySet()
System.out.println("Keys: " + numbers.keySet());

// Using values()
System.out.println("Values: " + numbers.values());
}
}

输出:

1
2
3
4
LinkedHashMap: {One=1, Two=2, Three=3}
Key/Value mappings: [One=1, Two=2, Three=3]
Keys: [One, Two, Three]
Values: [1, 2, 3]
  • get() - 返回与指定key关联的value。如果找不到该键,则返回null
  • getOrDefault() - 返回与指定key关联的value。 如果key没有找到则返回默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {

LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("LinkedHashMap: " + numbers);

// Using get()
int value1 = numbers.get("Three");
System.out.println("Returned Number: " + value1);

// Using getOrDefault()
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("Returned Number: " + value2);
}
}

输出:

1
2
3
LinkedHashMap: {One=1, Two=2, Three=3}
Returned Number: 3
Returned Number: 5

移除 LinkedHashMap中的元素

  • remove(key) - 返回并从map中删除与指定key关联的条目
  • remove(key, value) - 当keyvalue匹配时才从map中删除,返回boolean值说明删除是否成功。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.LinkedHashMap;

class Main {
public static void main(String[] args) {

LinkedHashMap<String, Integer> numbers = new LinkedHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("LinkedHashMap: " + numbers);

// remove method with single parameter
int value = numbers.remove("Two");
System.out.println("Removed value: " + value);

// remove method with two parameters
boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry Three removed? " + result);

System.out.println("Updated LinkedHashMap: " + numbers);
}
}

输出:

1
2
3
4
LinkedHashMap: {One=1, Two=2, Three=3}
Removed value: 2
Is the entry {Three=3} removed? True
Updated LinkedHashMap: {One=1}

LinkedHashMap中其他方法

Method Description
clear() map上删除所有条目
containsKey() 检查map是否包含指定的key并返回布尔值
containsValue() 检查map是否包含指定的value并返回布尔值
size() 返回map大小
isEmpty() 检查map是否为空并返回布尔值

LinkedHashMap Vs. HashMap

LinkedHashMapHashMap都实现Map接口,但它们存在一些差别

  • LinkedHashMap在内部维护一个双向链接列表。因此,它保持其元素的插入顺序。
  • LinkedHashMap类比`HashMap需要更多的存储空间。这是因为LinkedHashMap在内部维护链接列表。
  • LinkedHashMap的性能比HashMap慢。

WeakHashMap

Java collections framework 中的WeakHashMap类提供了哈希表数据结构的功能。

注意:weak hashmap中key是 弱引用 类型

如果引用不再在程序中使用,则弱引用类型的对象可以在Java中被垃圾回收。

创建一个 WeakHashMap

为了创建一个weakHashMap,我们必须首先导入java.util.WeakHashMap

1
2
//WeakHashMap creation with capacity 8 and load factor 0.6
WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8, 0.6);

在上面的代码中,我们创建了一个名为NumbersWeakHashMap

  • Key - 用于关联map中每个元素(value)的唯一标识符
  • Value - map中按key所关联的元素

注意新的LinkedHashMap <>(8,0.6)部分。在这里,第一个参数是容量,第二个参数是负载系数。

  • 8(容量是 8) - 这意味着它可以存储8个条目。
  • 0.6f(负载系数为0.6) - 这意味着只要我们的哈希表填充了60%,条目将移至新的哈希表,其大小是原始哈希表的两倍.

如果未使用可选参数,则默认容量为16,默认负载系数为0.75。

HashMap 和 WeakHashMap

让我们看看Java中weak Hash Map的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating WeakHashMap of numbers
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;

// Inserting elements
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("WeakHashMap: " + numbers);

// Make the reference null
two = null;

// Perform garbage collection
System.gc();

System.out.println("WeakHashMap after garbage collection: " + numbers);
}
}

输出:

1
2
WeakHashMap: {Four=4, Two=2}
WeakHashMap after garbage collection: {Four}

如我们所见,当weakHashMapkey是2设置为null并执行垃圾回收时,该键将被删除。

因为与hashMap不同,weakHashMap中的key弱引用类型。这意味着,如果不再使用映射条目,则垃圾收集器将删除该条目。这对于节省资源很有用。

现在让我们在hashMap中查看相同的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.HashMap;

class Main {
public static void main(String[] args) {
// Creating HashMap of even numbers
HashMap<String, Integer> numbers = new HashMap<>();

String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;

// Inserting elements
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("HashMap: " + numbers);

// Make the reference null
two = null;

// Perform garbage collection
System.gc();

System.out.println("HashMap after garbage collection: " + numbers);
}
}

输出:

1
2
HashMap: {Four=4, Two=2}
HashMap after garbage collection: {Four=4, Two=2}

在这里,当hashMapkey是2设置为null并执行垃圾回收时,不会删除该键。

这是因为与weakHashMap不同,hashMapkey具有强引用类型。这意味着垃圾回收器不会删除映射的条目,即使不再使用该条目的键。

hashMapweakHashMap的所有功能都相似,只是weakHashMap的键具有弱引用性,而hashMap的键具有强引用性。

创建一个 WeakHashMap从其它Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.HashMap;
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating a hashmap of even numbers
HashMap<String, Integer> evenNumbers = new HashMap<>();

String two = new String("Two");
Integer twoValue = 2;
evenNumbers.put(two, twoValue);
System.out.println("HashMap: " + evenNumbers);

// Creating a weak hash map from other hashmap
WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers);

System.out.println("WeakHashMap: " + numbers);
}
}

输出:

1
2
HashMap: {Two=2}
WeakHashMap: {Two=2}

WeakHashMap中的方法

插入元素

  • put() - 将指定的key/value插入到map
  • putAll() - 将指定map中的所有条目插入此map中
  • putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入到map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating WeakHashMap of even numbers
WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>();

String two = new String("Two");
Integer twoValue = 2;

// Using put()
evenNumbers.put(two, twoValue);

String four = new String("Four");
Integer fourValue = 4;

// Using putIfAbsent()
evenNumbers.putIfAbsent(four, fourValue);
System.out.println("WeakHashMap of even numbers: " + evenNumbers);

//Creating WeakHashMap of numbers
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

String one = new String("One");
Integer oneValue = 1;
numbers.put(one, oneValue);

// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("WeakHashMap of numbers: " + numbers);
}
}

输出:

1
2
WeakHashMap of even numbers: {Four=4, Two=2}
WeakHashMap of numbers: {Two=2, Four=4, One=1}

获取元素

  • entrySet() - 获取map中key/value的集合
  • keySet() - 获取mapkeys的集合
  • values() - 获取mapvalues的集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating WeakHashMap of even numbers
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

String one = new String("One");
Integer oneValue = 1;
numbers.put(one, oneValue);

String two = new String("Two");
Integer twoValue = 2;
numbers.put(two, twoValue);

System.out.println("WeakHashMap: " + numbers);

// Using entrySet()
System.out.println("Key/Value mappings: " + numbers.entrySet());

// Using keySet()
System.out.println("Keys: " + numbers.keySet());

// Using values()
System.out.println("Values: " + numbers.values());
}
}

输出:

1
2
3
4
WeakHashMap: {Two=2, One=1}
Key/Value mappings: [Two=2, One=1]
Keys: [Two, One]
Values: [1, 2]
  • get() - 返回与指定key关联的value。如果找不到该键,则返回null
  • getOrDefault() - 返回与指定key关联的value。 如果key没有找到则返回默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating WeakHashMap of even numbers
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

String one = new String("One");
Integer oneValue = 1;
numbers.put(one, oneValue);

String two = new String("Two");
Integer twoValue = 2;
numbers.put(two, twoValue);

System.out.println("WeakHashMap: " + numbers);

// Using get()
int value1 = numbers.get("Two");
System.out.println("Using get(): " + value1);

// Using getOrDefault()
int value2 = numbers.getOrDefault("Four", 4);
System.out.println("Using getOrDefault(): " + value2);

}
}

输出:

1
2
3
WeakHashMap: {Two=2, One=1}
Using get(): 2
Using getOrDefault(): 4

移除元素

  • remove(key) - 返回并从map中删除与指定key关联的条目
  • remove(key, value) - 当keyvalue匹配时才从map中删除,返回boolean值说明删除是否成功。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.WeakHashMap;

class Main {
public static void main(String[] args) {
// Creating WeakHashMap of even numbers
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();

String one = new String("One");
Integer oneValue = 1;
numbers.put(one, oneValue);

String two = new String("Two");
Integer twoValue = 2;
numbers.put(two, twoValue);

System.out.println("WeakHashMap: " + numbers);

// Using remove() with single parameter
int value = numbers.remove("Two");
System.out.println("Removed value: " + value);

// Using remove() with 2 parameters
boolean result = numbers.remove("One", 3);
System.out.println("Is the entry {One=3} removed? " + result);

System.out.println("Updated WeakHashMap: " + numbers);
}
}

输出:

1
2
3
4
WeakHashMap: {Two=2, One=1}
Removed value: 2
Is the entry {One=3} removed? False
Updated WeakHashMap: {One=1}

WeakHashMap中其他方法

Method Description
clear() map上删除所有条目
containsKey() 检查map是否包含指定的key并返回布尔值
containsValue() 检查map是否包含指定的value并返回布尔值
size() 返回map大小
isEmpty() 检查map是否为空并返回布尔值

EnumMap

java collections frameworkEnumMap提供了在Map中实现枚举的能力。

EnumMap中,枚举元素用作keys,它实现了Map接口。

创建一个 EnumMap

为了创建一个EnumMap,我们必须首先导入java.util.EnumMap包。

1
2
3
4
5
enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);

在上面的示例中,我们创建了一个名为sizeEnumMap

  • Size - map中的keys枚举值
  • Integer - 与keys相关联的value值

EnumMap中的方法

插入元素

  • put() - 将key/value插入到EnumMap 中
  • putAll() - 将指定的map数据全部插入到当前map中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.EnumMap;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {

// Creating an EnumMap of the Size enum
EnumMap<Size, Integer> sizes1 = new EnumMap<>(Size.class);

// Using the put() Method
sizes1.put(Size.SMALL, 28);
sizes1.put(Size.MEDIUM, 32);
System.out.println("EnumMap1: " + sizes1);

EnumMap<Size, Integer> sizes2 = new EnumMap<>(Size.class);

// Using the putAll() Method
sizes2.putAll(sizes1);
sizes2.put(Size.LARGE, 36);
System.out.println("EnumMap2: " + sizes2);
}
}

输出:

1
2
EnumMap1: {SMALL=28, MEDIUM=32}
EnumMap2: {SMALL=28, MEDIUM=32, LARGE=36}

在上面的示例中,我们使用putAll()方法将enum map size1的所有元素插入到enum map size2的中。

enum map的putAll()还插入其他类型的map(HashMapTreeMap).但是,所有map都应具有相同的枚举类型。

获取元素

  • entrySet() - 返回一个enum map的所有key/value映射(条目)的集合
  • keySet() - 返回一个enum map中所有的keys集合
  • values() - 返回一个enum map中所有的values集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.EnumMap;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {

// Creating an EnumMap of the Size enum
EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
sizes.put(Size.SMALL, 28);
sizes.put(Size.MEDIUM, 32);
sizes.put(Size.LARGE, 36);
sizes.put(Size.EXTRALARGE, 40);
System.out.println("EnumMap: " + sizes);

// Using the entrySet() Method
System.out.println("Key/Value mappings: " + sizes.entrySet());

// Using the keySet() Method
System.out.println("Keys: " + sizes.keySet());

// Using the values() Method
System.out.println("Values: " + sizes.values());
}
}

输出:

1
2
3
4
EnumMap: {SMALL=28, MEDIUM=32, LARGE=36, EXTRALARGE=40}
Key/Value mappings: [SMALL=28, MEDIUM=32, LARGE=36, EXTRALARGE=40]
Keys: [SMALL, MEDIUM, LARGE, EXTRALARGE]
Values: [28, 32, 36, 40]
  • get(key) - 指定的key返回value,如果key不存在则返回null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.EnumMap;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {

// Creating an EnumMap of the Size enum
EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
sizes.put(Size.SMALL, 28);
sizes.put(Size.MEDIUM, 32);
sizes.put(Size.LARGE, 36);
sizes.put(Size.EXTRALARGE, 40);
System.out.println("EnumMap: " + sizes);

// Using the get() Method
int value = sizes.get(Size.MEDIUM);
System.out.println("Value of MEDIUM: " + value);
}
}

输出:

1
2
EnumMap: {SMALL=28, MEDIUM=32, LARGE=36, EXTRALARGE=40}
Value of MEDIUM: 32

移除元素

  • remove(key) - 根据key删除数据,如果删除成功则返回该数据
  • remove(key, value) - 当map中存在key/value匹配情况则删除,返回boolean类型值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.EnumMap;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {

// Creating an EnumMap of the Size enum
EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
sizes.put(Size.SMALL, 28);
sizes.put(Size.MEDIUM, 32);
sizes.put(Size.LARGE, 36);
sizes.put(Size.EXTRALARGE, 40);
System.out.println("EnumMap: " + sizes);

// Using the remove() Method
int value = sizes.remove(Size.MEDIUM);
System.out.println("Removed Value: " + value);

boolean result = sizes.remove(Size.SMALL, 28);
System.out.println("Is the entry {SMALL=28} removed? " + result);

System.out.println("Updated EnumMap: " + sizes);
}
}

输出:

1
2
3
4
EnumMap: {SMALL=28, MEDIUM=32, LARGE=36, EXTRALARGE=40}
Removed Value: 32
Is the entry {SMALL=28} removed? True
Updated EnumMap: {LARGE=36, EXTRALARGE=40}

替换元素

  • replace(key, value) - 将key对于的值替换成value
  • replace(key, old, new) - 如果key对于的值是old则替换成new
  • replaceAll(function) - 将map的每个值替换为指定函数的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.EnumMap;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}
public static void main(String[] args) {

// Creating an EnumMap of the Size enum
EnumMap<Size, Integer> sizes = new EnumMap<>(Size.class);
sizes.put(Size.SMALL, 28);
sizes.put(Size.MEDIUM, 32);
sizes.put(Size.LARGE, 36);
sizes.put(Size.EXTRALARGE, 40);
System.out.println("EnumMap: " + sizes);

// Using the replace() Method
sizes.replace(Size.MEDIUM, 30);
sizes.replace(Size.LARGE, 36, 34);
System.out.println("EnumMap using replace(): " + sizes);

// Using the replaceAll() Method
sizes.replaceAll((key, oldValue) -> oldValue + 3);
System.out.println("EnumMap using replaceAll(): " + sizes);
}
}

输出:

1
2
3
EnumMap: {SMALL=28, MEDIUM=32, LARGE=36, EXTRALARGE=40}
EnumMap using replace(): {SMALL=28, MEDIUM=30, LARGE=34, EXTRALARGE=40}
EnumMap using replaceAll(): {SMALL=31, MEDIUM=33, LARGE=37, EXTRALARGE=43}

EnumMap中其他方法

Method Description
clone() 创建EnumMap的副本
containsKey() EnumMap中搜索指定的键,并返回一个布尔结果
containsValue() EnumMap中搜索指定的值,并返回一个布尔结果
size() 返回EnumMap的大小
clear() EnumMap中删除所有条目

EnumSet Vs. EnumMap

EnumSetEnumMap类都提供数据结构来存储枚举值。但是,它们之间存在一些主要差异。

  • EnumSet在内部以位序列表示,而EnumMap在内部以数组表示。
  • EnumSet是使用其预定义方法(例如allOf()noneOf()of()),但是,EnumMap是使用其构造函数创建的。

可克隆和可序列化的接口

EnumMap类还实现了CloneableSerializable接口。

Cloneable

它允许EnumMap类制作该类实例的副本。

Serializable

每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。

Serializable接口允许对类进行序列化。这意味着可以将实现Serializable的类的对象转换为位或字节。

SortedMap

Java collections frameworkSortedMap接口可对存储在map中的key进行排序。

实现 SortedMap的类

由于SortedMap是一个接口,因此无法从中创建对象。

为了使用SortedMap接口的功能,我们需要使用实现该接口的类TreeMap

怎么使用SortedMap

要使用SortedMap,我们必须首先导入java.util.SortedMap包。

1
2
// SortedMap implementation by TreeMap class
SortedMap<Key, Value> numbers = new TreeMap<>();
  • key - 用于关联map中每个元素(值)的唯一标识符
  • Value-map中按key关联的元素

在这里,我们没有使用任何参数来创建排序的map,因此,map将自然排序(升序)。

SortedMap中的方法

SortedMap接口包含Map接口的所有方法。这是因为MapSortedMap的超级接口。

除了所有这些方法之外,以下是SortedMap接口专用的方法。

  • comparator() -返回一个可用于对map中的key进行排序的比较器
  • firstKey() - 返回已排序映射的第一个key
  • lastKey() - 返回已排序映射的最后一个key
  • headMap(key) - 返回其key小于指定key的map的所有条目
  • tailMap(key) - 返回其key大于或等于指定键的映射的所有条目
  • subMap(key1, key2) - 返回其key位于key1key2之间(包括key1)的map的所有条目

TreeMap实现SortedMap类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.SortedMap;
import java.util.TreeMap;

class Main {

public static void main(String[] args) {
// Creating SortedMap using TreeMap
SortedMap<String, Integer> numbers = new TreeMap<>();

// Insert elements to map
numbers.put("Two", 2);
numbers.put("One", 1);
System.out.println("SortedMap: " + numbers);


// Access the first key of the map
System.out.println("First Key: " + numbers.firstKey());

// Access the last key of the map
System.out.println("Last Key: " + numbers.lastKey());

// Remove elements from the map
int value = numbers.remove("One");
System.out.println("Removed Value: " + value);
}
}

输出:

1
2
3
4
SortedMap: {One=1, Two=2}
First Key: One
Last Key: Two
Removed Value: 1

Java collections frameworkNavigableMap提供了 map中数据互相导航的能力

NavigableMap继承至SortedMap

实现NavigableMap的类

由于NavigableMap是一个接口,因此我们无法从中创建对象。

为了使用NavigableMap接口的功能,我们需要使用实现NavigableMapTreeMap类。

怎么使用 NavigableMap

在Java中,我们必须导入java.util.NavigableMap包才能使用NavigableMap

1
2
// NavigableMap implementation by TreeMap class
NavigableMap<Key, Value> numbers = new TreeMap<>();

在上面的代码中,我们创建了一个名为numbersTreeMap类。

  • Key - 用于关联map中每个元素(值)的唯一标识符
  • Value - map中按key关联的元素

NavigableMap被视为SortedMap的一种。这是因为NavigableMap扩展了SortedMap接口。因此,所有的SortedMap方法在NavigableMap中也可用。

但是,在NavigableMap中对SortedMap的某些方法(headMap()tailMap()subMap())进行了不同的定义。

headMap(key, booleanValue)

headMap()会将navigable mapkey之前所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true

如果booleanValuetrue,表示该方法返回key之前的keys所有关联数据包括key本身

tailMap(key, booleanValue)

tailMap()会将navigable mapkey之后所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true

如果booleanValue是个false,则该方法返回key之后keys所有关联数据包括key本身

subMap(k1, bv1, k2, bv2)

subMap()返回k1k2之间所有的数据,包括k1数据

bv1bv2是可选参数。 bv1的默认值为truebv2的默认值为false

如果将bv1设为false,则返回k1k2之间所有的数据,不包括k1数据

如果将bv2设为true,则返回k1k2之间所有的数据,包括k2的数据

其它方法

NavigableMap提供了各种用于设置数据在map中位置的方法。

  • descendingMap()-反转map中的数据顺序
  • descendingKeyMap() - 反转map中keys的顺序
  • ceilingEntry() - 返回所有大于或等于指定key中,最小key关联的数据
  • ceilingKey() - 返回所有大于或等于指定key中,最小key
  • floorEntry() - 返回所有小于或等于指定key中,最大key关联的数据
  • floorKey() - 返回所有小于或等于指定key中,最大key
  • higherEntry() - 返回所有大于指定key中,最小key关联的数据
  • higherKey() - 返回所有大于指定key中,最小key
  • lowerEntry() - 返回所有小于指定key中,最大key关联的数据
  • lowerKey() - 返回所有小于指定key中,最大的key
  • firstEntry() - 返回map的第一个数据(具有最小key的数据)
  • lastEntry() - 返回map中最后一个数据(具有最大key的数据)
  • pollFirstEntry() - 返回并删除map中第一个数据
  • pollLastEntry() - 返回并删除map中最后一个数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.NavigableMap;
import java.util.TreeMap;

class Main {

public static void main(String[] args) {
// Creating NavigableMap using TreeMap
NavigableMap<String, Integer> numbers = new TreeMap<>();

// Insert elements to map
numbers.put("Two", 2);
numbers.put("One", 1);
numbers.put("Three", 3);
System.out.println("NavigableMap: " + numbers);

// Access the first entry of the map
System.out.println("First Entry: " + numbers.firstEntry());

// Access the last entry of the map
System.out.println("Last Entry: " + numbers.lastEntry());

// Remove the first entry from the map
System.out.println("Removed First Entry: " + numbers.pollFirstEntry());

// Remove the last entry from the map
System.out.println("Removed Last Entry: " + numbers.pollLastEntry());
}
}

输出:

1
2
3
4
5
NavigableMap: {One=1, Three=3, Two=2}
First Entry: One=1
Last Entry: Two=2
Removed First Entry: One=1
Removed Last Entry: Two=2

TreeMap

Java collections framework提供了 tree数据结构的实现

创建 TreeMap

为了创建TreeMap,我们必须首先导入java.util.TreeMap包。

1
TreeMap<Key, Value> numbers = new TreeMap<>();

在上面的代码中,我们创建了一个名为NumbersTreeMap,没有任何参数。在这种情况下,TreeMap中的元素会自然排序(升序)。但是,我们可以使用Comparator接口自定义元素的排序。

  • Key - 用于关联map中每个元素(值)的唯一标识符
  • Value - map中按key关联的元素

TreeMap 中的方法

插入元素

  • put() - 将指定的key/value插入到map中
  • putAll() - 将指定到map所有数据插入到当前map中
  • putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value映射插入map中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.TreeMap;

class Main {
public static void main(String[] args) {
// Creating TreeMap of even numbers
TreeMap<String, Integer> evenNumbers = new TreeMap<>();

// Using put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);

// Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("TreeMap of even numbers: " + evenNumbers);

//Creating TreeMap of numbers
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);

// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("TreeMap of numbers: " + numbers);
}
}

输出:

1
2
TreeMap of even numbers: {Four=4, Six=6, Two=2}
TreeMap of numbers: {Four=4, One=1, Six=6, Two=2}

获取元素

  • entrySet() - 返回 treemap中所有key/value集合
  • keySet() - 返回treemap中所有key集合
  • values() - 返回treemap中所有value集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();

numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// Using entrySet()
System.out.println("Key/Value mappings: " + numbers.entrySet());

// Using keySet()
System.out.println("Keys: " + numbers.keySet());

// Using values()
System.out.println("Values: " + numbers.values());
}
}

输出:

1
2
3
4
TreeMap: {One=1, Three=3, Two=2}
Key/Value mappings: [One=1, Three=3, Two=2]
Keys: [One, Three, Two]
Values: [1, 3, 2]
  • get(key) - 返回与指定key关联的value。如果找不到key,则返回null
  • getOrDefault(key,defalutValue) - 返回与指定key关联的value。如果找不到key,则返回指定的默认值(defalutValue)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// Using get()
int value1 = numbers.get("Three");
System.out.println("Using get(): " + value1);

// Using getOrDefault()
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("Using getOrDefault(): " + value2);
}
}

输出:

1
2
3
TreeMap: {One=1, Three=3, Two=2}
Using get(): 3
Using getOrDefault(): 5

移除元素

  • remove(key) - 返回并从TreeMap中删除与指定key关联的数据
  • remove(key, value) - 仅当指定key与指定value相关联时才从map中删除数据,并返回布尔值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("TreeMap: " + numbers);

// remove method with single parameter
int value = numbers.remove("Two");
System.out.println("Removed value: " + value);

// remove method with two parameters
boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry {Three=3} removed? " + result);

System.out.println("Updated TreeMap: " + numbers);
}
}

输出:

1
2
3
4
TreeMap: {One=1, Three=3, Two=2}
Removed value = 2
Is the entry {Three=3} removed? True
Updated TreeMap: {One=1}

替换元素

  • replace(key, value) - 用新值value替换key关联的旧值
  • replace(key, old, new) -仅当旧值已与指定key关联时,才用新值替换旧值
  • replaceAll(function) - 将map的每个value替换为指定函数的结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("Original TreeMap: " + numbers);

// Using replace()
numbers.replace("Second", 22);
numbers.replace("Third", 3, 33);
System.out.println("TreeMap using replace: " + numbers);

// Using replaceAll()
numbers.replaceAll((key, oldValue) -> oldValue + 2);
System.out.println("TreeMap using replaceAll: " + numbers);
}
}

输出:

1
2
3
Original TreeMap: {First=1, Second=2, Third=3}
TreeMap using replace(): {First=1, Second=22, Third=33}
TreeMap using replaceAll(): {First=3, Second=24, Third=35}

由于TreeMap类实现了NavigableMap,因此它提供了各种方法来浏览treemap的元素。

First and Last Methods

  • firstKey() - 返回 map 第一个key
  • firstEntry() - 返回map 第一个key 的数据(key/value)
  • lastKey() - 返回map最后一个key
  • lastEntry() - 返回map最后一个key的数据(key/value)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.TreeMap;

class Main {
public static void main(String[] args) {
TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);

// Using the firstKey() method
String firstKey = numbers.firstKey();
System.out.println("First Key: " + firstKey);

// Using the lastKey() method
String lastKey = numbers.lastKey();
System.out.println("Last Key: " + lastKey);

// Using firstEntry() method
System.out.println("First Entry: " + numbers.firstEntry());


// Using the lastEntry() method
System.out.println("Last Entry: " + numbers.lastEntry());
}
}

输出:

1
2
3
4
5
TreeMap: {First=1, Second=2, Third=3}
First Key: First
Last Key: Third
First Entry: First=1
Last Entry: Third=3

Ceiling、Floor、Higher and Lower Methods

  • ceilingEntry() - 返回所有大于或等于指定key中,最小key关联的数据
  • ceilingKey() - 返回所有大于或等于指定key中,最小key
  • floorEntry() - 返回所有小于或等于指定key中,最大key关联的数据
  • floorKey() - 返回所有小于或等于指定key中,最大key
  • higherEntry() - 返回所有大于指定key中,最小key关联的数据
  • higherKey() - 返回所有大于指定key中,最小key
  • lowerEntry() - 返回所有小于指定key中,最大key关联的数据
  • lowerKey() - 返回所有小于指定key中,最大的key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 5);
numbers.put("Third", 4);
numbers.put("Fourth", 6);
System.out.println("TreeMap: " + numbers);

// Using higher()
System.out.println("Using higherKey(): " + numbers.higherKey("Fourth"));
System.out.println("Using higherEntry(): " + numbers.higherEntry("Fourth"));

// Using lower()
System.out.println("\nUsing lowerKey(): " + numbers.lowerKey("Fourth"));
System.out.println("Using lowerEntry(): " + numbers.lowerEntry("Fourth"));

// Using ceiling()
System.out.println("\nUsing ceilingKey(): " + numbers.ceilingKey("Fourth"));
System.out.println("Using ceilingEntry(): " + numbers.ceilingEntry("Fourth"));

// Using floor()
System.out.println("\nUsing floorKey(): " + numbers.floorKey("Fourth"));
System.out.println("Using floorEntry(): " + numbers.floorEntry("Fourth"));


}
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
TreeMap: {First=1, Fourth=6, Second=5, Third=4}
Using higherKey(): Second
Using higherEntry(): Second=5

Using lowerKey(): First
Using lowerEntry(): First=1

Using ceilingKey(): Fourth
Using ceilingEntry(): Fourth=6

Using floorkey(): Fourth
Using floorEntry(): Fourth=6

pollFirstEntry() and pollLastEntry() Methods

  • pollFirstEntry() - 返回并删除map中第一个数据
  • pollLastEntry() - 返回并删除map中最后一个数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
System.out.println("TreeMap: " + numbers);

//Using the pollFirstEntry() method
System.out.println("Using pollFirstEntry(): " + numbers.pollFirstEntry());

// Using the pollLastEntry() method
System.out.println("Using pollLastEntry(): " + numbers.pollLastEntry());

System.out.println("Updated TreeMap: " + numbers);

}
}

输出:

1
2
3
4
TreeMap: {First=1, Second=2, Third=3}
Using pollFirstEntry(): First=1
Using pollLastEntry(): Third=3
Updated TreeMap: {Second=2}

headMap(), tailMap() and subMap() Methods

headMap(key,booleanValue)

headMap()会将treemapkey之前所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true

如果booleanValuetrue,表示该方法返回key之前的keys所有关联数据包括key本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\nUsing headMap() Method:");
// Using headMap() with default booleanValue
System.out.println("Without boolean value: " + numbers.headMap("Fourth"));

// Using headMap() with specified booleanValue
System.out.println("With boolean value: " + numbers.headMap("Fourth", true));

}
}

输出:

1
2
3
4
5
TreeMap: {First=1, Fourth=4, Second=2, Third=3}

Using headMap() Method:
Without boolean value: {First=1}
With boolean value: {First=1, Fourth=4}

tailMap(key, booleanValue)

tailMap()会将treemapkey之后所有keys相关关联的数据返回。booleanValue是一个可选参数,默认是true

如果booleanValue是个false,则该方法返回key之后keys所有关联数据包括key本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\nUsing tailMap() Method:");
// Using tailMap() with default booleanValue
System.out.println("Without boolean value: " + numbers.tailMap("Second"));

// Using tailMap() with specified booleanValue
System.out.println("With boolean value: " + numbers.tailMap("Second", false));

}
}

输出:

1
2
3
4
5
TreeMap: {First=1, Fourth=4, Second=2, Third=3}

Using tailMap() Method:
Without boolean value: {Second=2, Third=3}
With boolean value: {Third=3}

subMap(k1, bV1, k2, bV2)

subMap()返回k1k2之间所有的数据,包括k1数据

bv1bv2是可选参数。 bv1的默认值为truebv2的默认值为false

如果将bv1设为false,则返回k1k2之间所有的数据,不包括k1数据

如果将bv2设为true,则返回k1k2之间所有的数据,包括k2的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeMap;

class Main {
public static void main(String[] args) {

TreeMap<String, Integer> numbers = new TreeMap<>();
numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);

System.out.println("\nUsing subMap() Method:");
// Using subMap() with default booleanValue
System.out.println("Without boolean value: " + numbers.subMap("Fourth", "Third"));

// Using subMap() with specified booleanValue
System.out.println("With boolean value: " + numbers.subMap("Fourth", false, "Third", true));

}
}

输出:

1
2
3
4
5
TreeMap: {First=1, Fourth=2, Second=2, Third=3}

Using subMap() Method:
Without boolean value: {Fourth=4, Second=2}
With boolean value: {Second=2, Third=3}

其它方法

Method Description
clone() 创建TreeMap的副本
containsKey() 在TreeMap中搜索指定的key,并返回布尔结果
containsValue() 在TreeMap中搜索指定的value并返回布尔结果
size() 返回TreeMap的大小
clear() 从TreeMap中删除所有条目

TreeMap Comparator

treemap元素默认是自然排序(以升序排列)。但是,我们也可以自定义key的顺序。

为此,我们需要基于treemap中的key排序来创建自己的比较器类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.TreeMap;
import java.util.Comparator;

class Main {
public static void main(String[] args) {

// Creating a treemap with a customized comparator
TreeMap<String, Integer> numbers = new TreeMap<>(new CustomComparator());

numbers.put("First", 1);
numbers.put("Second", 2);
numbers.put("Third", 3);
numbers.put("Fourth", 4);
System.out.println("TreeMap: " + numbers);
}

// Creating a comparator class
public static class CustomComparator implements Comparator<String> {

@Override
public int compare(String number1, String number2) {
int value = number1.compareTo(number2);

// elements are sorted in reverse order
if (value > 0) {
return -1;
}
else if (value < 0) {
return 1;
}
else {
return 0;
}
}
}
}

输出:

1
TreeMap: {Third=3, Second=2, Fourth=4, First=1}

在上面的示例中,我们创建了一个treemap,将CustomComparator类作为参数传递。

CustomComparator类实现Comparator接口。

然后,我们重写compare()方法,以相反的顺序对元素进行排序。

ConcurrentMap

Java collections frameworkconcurrentMap提供线程安全的map.也就是说,多个线程可以一次访问map,而不会影响映射中条目的一致性。

concurrentMap被称为同步map

实现concurrentMap的 class

concurrentMap是个接口,我们不能通过它创建对象。

如果我们想使用concurrentMap中的方法,我们需要使用concurrentHashMap类,它是concurrentMap的实现。

怎样使用 concurrentMap

要使用ConcurrentMap,我们必须首先导入java.util.concurrent.ConcurrentMap包。导入包后,将按照以下方法创建concurrentMap

1
2
// ConcurrentMap implementation by ConcurrentHashMap
ConcurrentMap<Key, Value> numbers = new ConcurrentHashMap<>();

在上面的代码中,我们创建了一个名为NumbersconcurrentMap

  • Key - 用于关联map每个元素(value)的唯一标识符.
  • Value - map中按key关联的元素.

concurrentMap中的方法

ConcurrentMap接口包含Map接口的所有方法。这是因为MapConcurrentMap接口的超级接口。

除了所有这些方法外,以下是ConcurrentMap接口特定的方法。

  • putIfAbsent() - 如果指定的key/value尚未与任何值关联,则将其插入到map中。
  • compute() - 计算指定key的数据及其它之前的value
  • computeIfAbsent() - 如果自定的key尚未于map中任何value有关联,则通过传入的函数计算一个value与其关联。
  • computeIfPresent() - 如果指定的key有关联的value,则计算一个新的值。
  • forEach() - 访问map的所有条目并执行指定的操作。
  • merge() - 如果key已经映射到某个特定value,则将新的指定value与指定key的旧值合并。如果该key尚未映射,则该方法只需将指定的value与我们的key关联。

concurrentHashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;

class Main {

public static void main(String[] args) {
// Creating ConcurrentMap using ConcurrentHashMap
ConcurrentMap<String, Integer> numbers = new ConcurrentHashMap<>();

// Insert elements to map
numbers.put("Two", 2);
numbers.put("One", 1);
numbers.put("Three", 3);
System.out.println("ConcurrentMap: " + numbers);

// Access the value of specified key
int value = numbers.get("One");
System.out.println("Accessed Value: " + value);

// Remove the value of specified key
int removedValue = numbers.remove("Two");
System.out.println("Removed Value: " + removedValue);
}
}

输出:

1
2
3
ConcurrentMap: {One=1, Two=2, Three=3}
Accessed Value: 1
Removed Value: 2

concurrenthashmap

Javacollections frameworkconcurrentHashMap类提供了线程安全的映射.也就是说,多个线程可以一次访问map,而不会影响map中数据的一致性。

创建concurrentHashMap

为了创建concurrentHashMao,我们必须首先导入java.util.concurrent.ConcurrentHashMap包。

1
2
// ConcurrentHashMap with capacity 8 and load factor 0.6
ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f);
  • Key - 用于关联map每个元素(value)的唯一标识符.
  • Value - map中按key关联的元素.

注意: ** ConcurrentHashMap <>(8,0.6)部分。在这里,第一个参数是容量,第二个参数是负载系数**。

  • capacity - 该map的容量为 8。意味着,它可以存储8条数据。
  • loadFactor - map的负载系数是 0.6。它意味着当 hash table填充 60%时,会新增原 hash table 两倍数据量数据添加到原 hash table中。

默认 capacity 和 loadFactor

创建 concurrent hashmap可以不定义 capacityloadFactor.

1
2
// ConcurrentHashMap with default capacity and load factor
ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>();

capacity默认值是 16, loadFactor 默认值是 0.75.

通过另外的 map 创建 concurrentHashMap

这是我们如何创建包含其他映射的所有元素的concurrentHashMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.concurrent.ConcurrentHashMap;
import java.util.HashMap;

class Main {
public static void main(String[] args) {

// Creating a hashmap of even numbers
HashMap<String, Integer> evenNumbers = new HashMap<>();
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);
System.out.println("HashMap: " + evenNumbers);

// Creating a concurrent hashmap from other map
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(evenNumbers);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);
}
}

输出:

1
2
HashMap: {Four=4, Two=2}
ConcurrentHashMap: {Four=4, Two=2, Three=3}

concurrentHashMap 中的方法

插入元素

  • put() - 将指定的key/value数据插入到map中
  • putAll() - 将指定的map所有数据插入到当前map中
  • putIfAbsent() - 如果map中不存在指定的key,则将指定的key/value插入到map中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {
// Creating ConcurrentHashMap of even numbers
ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>();

// Using put()
evenNumbers.put("Two", 2);
evenNumbers.put("Four", 4);

// Using putIfAbsent()
evenNumbers.putIfAbsent("Six", 6);
System.out.println("ConcurrentHashMap of even numbers: " + evenNumbers);

//Creating ConcurrentHashMap of numbers
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);

// Using putAll()
numbers.putAll(evenNumbers);
System.out.println("ConcurrentHashMap of numbers: " + numbers);
}
}

输出:

1
2
ConcurrentHashMap of even numbers: {Six=6, Four=4, Two=2}
ConcurrentHashMap of numbers: {Six=6, One=1, Four=-4, Two=2}

获取元素

  • entrySet() - 返回map的所有key/value集合
  • keySet() - 返回map所有的key集合
  • valueSet() - 返回map所有的value集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();

numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// Using entrySet()
System.out.println("Key/Value mappings: " + numbers.entrySet());

// Using keySet()
System.out.println("Keys: " + numbers.keySet());

// Using values()
System.out.println("Values: " + numbers.values());
}
}

输出:

1
2
3
4
ConcurrentHashMap: {One=1, Two=2, Three=3}
Key/Value mappings: [One=1, Two=2, Three=3]
Keys: [One, Two, Three]
Values: [1, 2, 3]
  • get() - 返回与指定key关联的value。如果找不到密钥,则返回null
  • getOrDefault() - 返回与指定key关联的value。如果找不到密钥,则返回指定的默认值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {

ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// Using get()
int value1 = numbers.get("Three");
System.out.println("Using get(): " + value1);

// Using getOrDefault()
int value2 = numbers.getOrDefault("Five", 5);
System.out.println("Using getOrDefault(): " + value2);
}
}

输出:

1
2
3
ConcurrentHashMap: {One=1, Two=2, Three=3}
Using get(): 3
Using getOrDefault(): 5

移除元素

  • remove(key) - 返回并从map中删除与指定key关联的数据
  • remove(key, value) - 仅在将指定key映射到指定value时在map中删除数据,并返回布尔值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {

ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// remove method with single parameter
int value = numbers.remove("Two");
System.out.println("Removed value: " + value);

// remove method with two parameters
boolean result = numbers.remove("Three", 3);
System.out.println("Is the entry {Three=3} removed? " + result);

System.out.println("Updated ConcurrentHashMap: " + numbers);
}
}

输出:

1
2
3
4
ConcurrentHashMap: {One=1, Two=2, Three=3}
Removed value: 2
Is the entry {Three=3} removed? True
Updated ConcurrentHashMap: {One=1}

批量操作 concurrentHashMap

concurrentHashMap类提供了可以安全地应用于并发映射的不同批量操作。

forEach() 方法

forEach()方法遍历我们的数据目并执行指定的函数。它包含两个参数:

  • parallelismThreshold - 当数据量大于指定值时,进行并行计算。
  • transformer - 进行值处理的回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {

ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// forEach() without transformer function
numbers.forEach(4, (k, v) -> System.out.println("key: " + k + " value: " + v));

// forEach() with transformer function
System.out.print("Values are ");
numbers.forEach(4, (k, v) -> v, (v) -> System.out.print(v + ", "));
}
}

输出:

1
2
3
4
5
ConcurrentHashMap: {One = 1, Two = 2, Three = 3}
key: One value: 1
key: Two value: 2
key: Three value: 3
Values are 1, 2, 3,

在上面的程序中,我们使用了并行阈值4。这意味着,如果map包含4个条目,则该操作将并行执行。

forEach() 变形方法

  • forEachEntry() - 为每个数据执行指定的功能
  • forEachKey() - 为每个key执行指定的功能
  • forEachValue() - 为每个value执行指定的函数

search() 方法

search() 方法基于指定的函数搜索map,并返回匹配的条目。

在此,指定的功能确定要搜索的条目。

它还包括一个可选参数parallelThreshold。并行阈值指定在map中有多少个元素之后并行执行该操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {

ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// Using search()
String key = numbers.search(4, (k, v) -> {return v == 3 ? k: null;});
System.out.println("Searched value: " + key);

}
}

输出:

1
2
ConcurrentHashMap: {One=1, Two=2, Three=3}
Searched value: Three

search()的变形:

  • searchEntries() - 搜索功能应用于key/value映射
  • searchKeys() - 搜索功能仅适用于key
  • searchValues() - 搜索功能仅应用于value

reduce方法

reduce()方法累积(聚集)映射中的每条数据。当我们需要所有条数据来执行一项常见任务(例如添加地图的所有值)时,可以使用此方法。它有连个参数:

  • parallelismThreshold - 它指定在映射了几个元素之后,并行执行映射中的操作。
  • transformer - 进行数据处理的回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.concurrent.ConcurrentHashMap;

class Main {
public static void main(String[] args) {

ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>();
numbers.put("One", 1);
numbers.put("Two", 2);
numbers.put("Three", 3);
System.out.println("ConcurrentHashMap: " + numbers);

// Using search()
int sum = numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1 + v2);
System.out.println("Sum of all values: " + sum);

}
}

输出:

1
2
ConcurrentHashMap: {One=1, Two=2, Three=3}
Sum of all values: 6

在上面的程序中,请注意以下语句:

1
numbers.reduce(4, (k, v) -> v, (v1, v2) -> v1+v2);
  • 4 - 并行阈值
  • (k,v) -> v是转换函数。它将key/value映射仅转换为value
  • (v1, v2) -> v1+v2是一个累积函数。它收集所有value并添加所有值。

reduce()变形方法

  • reduceEntries() - 返回使用指定的reducer函数收集所有数据的结果
  • reduceKeys() - 返回使用指定的reducer函数收集所有key的结果
  • reduceValues() - 返回使用指定的reducer函数收集所有value的结果

ConcurrentHashMap vs HashMap

这是ConcurrentHashMapHashMap之间的一些区别:

  • ConcurrentHashMap是线程安全的集合。也就是说,多个线程可以同时访问和修改它。
  • ConcurrentHashMap提供了用于批量操作的方法,例如forEach()search()reduce()

ConcurrentHashMap 优势

  • ConcurrentHashMap类允许多个线程同时访问数据。
  • 默认情况下 concurrent hashmap是分为16段。这就是为什么允许16个线程同时并发修改映射的原因。但是,任何数量的线程一次都可以访问该map。
  • 如果指定的key已经存在,则putIfAbsent()方法将不会覆盖映射中的数据。
  • 它提供同步

Set

Java collections frameworkSet接口提供数学的集合 能力。它继承之collections接口。

List接口不同,Set不能包含重复的元素。

实现Set接口的类

由于Set是接口,因此我们无法从中创建对象。

为了使用Set接口的功能,我们可以使用以下类:

继承Set的接口

这些子接口还扩展了Set接口:

怎么使用 Set

在Java中,我们必须导入java.util.Set包才能使用Set

1
2
// Set implementation using HashSet
Set<String> animals = new HashSet<>();

在这里,我们创建了一个称为animalsSet。我们已经使用HashSet类实现Set接口。

Set中的方法

Set接口包含Collection接口的所有方法。

Set接口中还提供了Collection接口的一些常用方法:

  • add() - 将指定的元素添加到集合中
  • addAll() - 将指定集合的所有元素添加到集合中
  • iterator() - 返回一个迭代器,该迭代器可用于顺序访问集合中的元素
  • remove() - 从集合中移除指定的元素
  • removeAll() - 从存在于另一个指定集合中的集合中删除所有元素
  • retainAll() - 保留集合中也存在于另一个指定集合中的所有元素
  • clear() - 从集合中删除所有元素
  • size() - 返回集合的长度(元素数)
  • toArray() - 返回包含集合中所有元素的数组
  • contains() - 如果集合包含指定的元素,则返回true
  • containsAll() - 如果集合包含指定集合的所有元素,则返回true
  • hashCode() - 返回hash值(集合中元素的地址)

Set 操作符

Java Set接口允许我们执行基本的数学集合操作,例如并集,交集和子集。

  • Union - 要获得两个集合x和y的并集,我们可以使用x.addAll(y)
  • Intersection - 要获得两个集合x和y的交集,我们可以使用x.retainAll(y)
  • Subset - 要检查x是否是y的子集,我们可以使用y.containsAll(x)

Set接口的实现

HashSet 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Set;
import java.util.HashSet;

class Main {

public static void main(String[] args) {
// Creating a set using the HashSet class
Set<Integer> set1 = new HashSet<>();

// Add elements to the set1
set1.add(2);
set1.add(3);
System.out.println("Set1: " + set1);

// Creating another set using the HashSet class
Set<Integer> set2 = new HashSet<>();

// Add elements
set2.add(1);
set2.add(2);
System.out.println("Set2: " + set2);

// Union of two sets
set2.addAll(set1);
System.out.println("Union is: " + set2);
}
}

输出:

1
2
3
Set1: [2, 3]
Set2: [1, 2]
Union is: [1, 2, 3]

TreeSet 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;

class Main {

public static void main(String[] args) {
// Creating a set using the TreeSet class
Set<Integer> numbers = new TreeSet<>();

// Add elements to the set
numbers.add(2);
numbers.add(3);
numbers.add(1);
System.out.println("Set using TreeSet: " + numbers);

// Access Elements using iterator()
System.out.print("Accessing elements using iterator(): ");
Iterator<Integer> iterate = numbers.iterator();
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}

}
}

输出:

1
2
Set using TreeSet: [1, 2, 3]
Accessing elements using iterator(): 1, 2, 3,

Hashset

Java Collections frameworkHashSet类提供了hash table结构的功能。

创建 HashSet

为了创建hash set,我们必须首先导入java.util.HashSet包。

1
2
// HashSet with 8 capacity and 0.75 load factor
HashSet<Integer> numbers = new HashSet<>(8, 0.75);

注意,新的HashSet <>(8,0.75)部分。在这里,第一个参数是容量,第二个参数是负载系数。

  • capacity - 该hash st的容量为8。意味着,它可以存储8个元素。
  • loadFactor - 此hash set的负载系数为0.6。这意味着,只要我们的哈希集填充了60%,元素将移至新哈希表,其大小是原始哈希表的两倍。

默认 capacity 和 load factor

1
2
// HashSet with default capacity and load factor
HashSet<Integer> numbers1 = new HashSet<>();
  • 哈希集的容量将为16
  • 负载系数将为0.75

HashSet中的方法

插入元素

  • add() - 将指定的元素插入集合
  • addAll() - 将指定集合的所有元素插入集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> evenNumber = new HashSet<>();

// Using add() method
evenNumber.add(2);
evenNumber.add(4);
evenNumber.add(6);
System.out.println("HashSet: " + evenNumber);

HashSet<Integer> numbers = new HashSet<>();

// Using addAll() method
numbers.addAll(evenNumber);
numbers.add(5);
System.out.println("New HashSet: " + numbers);
}
}

输出:

1
2
HashSet: [2, 4, 6]
New HashSet: [2, 4, 5, 6]

获取元素

要访问hashset的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.HashSet;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
HashSet<Integer> numbers = new HashSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("HashSet: " + numbers);

// Calling iterator() method
Iterator<Integer> iterate = numbers.iterator();
System.out.print("HashSet using Iterator: ");
// Accessing elements
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
HashSet: [2, 5, 6]
HashSet using Iterator: 2, 5, 6,

移除元素

  • remvoe() - 从set中移除指定的元素
  • removeAll() - 从set中删除所有元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> numbers = new HashSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("HashSet: " + numbers);

// Using remove() method
boolean value1 = numbers.remove(5);
System.out.println("Is 5 removed? " + value1);

boolean value2 = numbers.removeAll(numbers);
System.out.println("Are all elements removed? " + value2);
}
}

输出:

1
2
3
HashSet: [2, 5, 6]
Is 5 removed? true
Are all elements removed? true

Set 操作符

HashSet类的各种方法也可以用于执行各种设置操作。

Union 操作

两个执行两个集合之间的联合,我们可以使用addAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> evenNumbers = new HashSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("HashSet1: " + evenNumbers);

HashSet<Integer> numbers = new HashSet<>();
numbers.add(1);
numbers.add(3);
System.out.println("HashSet2: " + numbers);

// Union of two set
numbers.addAll(evenNumbers);
System.out.println("Union is: " + numbers);
}
}

输出:

1
2
3
HashSet1: [2, 4]
HashSet2: [1, 3]
Union is: [1, 2, 3, 4]

Intersection 操作

为了执行两个集合之间的交集,我们可以使用retainAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> primeNumbers = new HashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("HashSet1: " + primeNumbers);

HashSet<Integer> evenNumbers = new HashSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("HashSet2: " + evenNumbers);

// Intersection of two sets
evenNumbers.retainAll(primeNumbers);
System.out.println("Intersection is: " + evenNumbers);
}
}

输出:

1
2
3
HashSet1: [2, 3]
HashSet2: [2, 4]
Intersection is: [2]

Difference 操作

要计算两组之间的差异,我们可以使用removeAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> primeNumbers = new HashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
primeNumbers.add(5);
System.out.println("HashSet1: " + primeNumbers);

HashSet<Integer> oddNumbers = new HashSet<>();
oddNumbers.add(1);
oddNumbers.add(3);
oddNumbers.add(5);
System.out.println("HashSet2: " + oddNumbers);

// Difference between HashSet1 and HashSet2
primeNumbers.removeAll(oddNumbers);
System.out.println("Difference : " + primeNumbers);
}
}

输出:

1
2
3
HashSet1: [2, 3, 5]
HashSet2: [1, 3, 5]
Difference: [2]

Subset

为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.HashSet;

class Main {
public static void main(String[] args) {
HashSet<Integer> numbers = new HashSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("HashSet1: " + numbers);

HashSet<Integer> primeNumbers = new HashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("HashSet2: " + primeNumbers);

// Check if primeNumbers is a subset of numbers
boolean result = numbers.containsAll(primeNumbers);
System.out.println("Is HashSet2 is subset of HashSet1? " + result);
}
}

输出:

1
2
3
HashSet1: [1, 2, 3, 4]
HashSet2: [2, 3]
Is HashSet2 is a subset of HashSet1? true

其它HashSet 方法

Method Description
clone() 创建HashSet的副本
contains() HashSet中搜索指定的元素并返回布尔结果
isEmpty() 检查`HashSet是否为空
size() 返回HashSet的大小
clear() HashSet中删除所有元素

HashSet 好处

在Java中,如果我们必须随机访问元素,则通常使用HashSet。这是因为使用哈希码访问哈希表中的元素。

元素的hashcode是唯一的标识,有助于标识哈希表中的元素。

HashSet不能包含重复的元素。因此,每个哈希集元素都有一个唯一的哈希码。

注意:HashSet不同步。也就是说,如果多个线程同时访问哈希集,并且其中一个线程修改了哈希集。然后必须从外部进行同步

EnumSet

Javacollections frameworkEnumSet类提供单个枚举元素的固定实现。

创建 EnumSet

为了创建一个枚举集,我们必须首先导入java.util.EnumSet包。

与其他集合实现不同,枚举集合没有公共构造函数。我们必须使用预定义的方法来创建一个枚举集。

allOf(Size)

allof()方法创建一个枚举集,其中包含指定枚举类型Size的所有值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.EnumSet;

class Main {
// an enum named Size
enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating an EnumSet using allOf()
EnumSet<Size> sizes = EnumSet.allOf(Size.class);

System.out.println("EnumSet: " + sizes);
}

}

输出:

1
EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE]

注意:

1
EnumSet<Size> sizes = EnumSet.allOf(Size.class);

在这里,Size.class表示我们创建的Size枚举。

noneOf(size)

noneOf()方法创建一个空的枚举集。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.EnumSet;

class Main {

// an enum type Size
enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating an EnumSet using noneOf()
EnumSet<Size> sizes = EnumSet.noneOf(Size.class);

System.out.println("Empty EnumSet: " + sizes);
}
}

输出:

1
Empty EnumSet : []

在这里,我们创建了一个空的枚举,名为sizes

注意: 我们只能在上述程序中插入枚举类型为Size的元素。这是因为我们使用Size枚举创建了空的枚举集。

range(e1, e2)

range()方法创建一个枚举集,其中包含e1e2之间的枚举的所有值,包括两个值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.EnumSet;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating an EnumSet using range()
EnumSet<Size> sizes = EnumSet.range(Size.MEDIUM, Size.EXTRALARGE);

System.out.println("EnumSet: " + sizes);
}
}

输出:

1
EnumSet: [MEDIUM, LARGE, EXTRALARGE]

of()

of()方法创建一个包含指定元素的枚举集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.EnumSet;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Using of() with a single parameter
EnumSet<Size> sizes1 = EnumSet.of(Size.MEDIUM);
System.out.println("EnumSet1: " + sizes1);

EnumSet<Size> sizes2 = EnumSet.of(Size.SMALL, Size.LARGE);
System.out.println("EnumSet2: " + sizes2);
}
}

输出:

1
2
EnumSet1: [MEDIUM]
EnumSet2: [SMALL, LARGE]

EnumSet 中方法

插入元素

  • add() - 将指定的枚举值插入到枚举集中
  • addAll() - 将指定集合的所有元素插入集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.EnumSet;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating an EnumSet using allOf()
EnumSet<Size> sizes1 = EnumSet.allOf(Size.class);

// Creating an EnumSet using noneOf()
EnumSet<Size> sizes2 = EnumSet.noneOf(Size.class);

// Using add method
sizes2.add(Size.MEDIUM);
System.out.println("EnumSet Using add(): " + sizes2);

// Using addAll() method
sizes2.addAll(sizes1);
System.out.println("EnumSet Using addAll(): " + sizes2);
}
}

输出:

1
2
EnumSet using add(): [MEDIUM]
EnumSet using addAll(): [SMALL, MEDIUM, LARGE, EXTRALARGE]

在上面的示例中,我们使用addAll()方法将枚举集size1的所有元素插入到枚举集size2中。

也可以使用addAll()将其他集合中的元素(例如ArrayListLinkedList等)插入到枚举集中。

获取元素

要访问一个枚举集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.EnumSet;
import java.util.Iterator;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating an EnumSet using allOf()
EnumSet<Size> sizes = EnumSet.allOf(Size.class);

Iterator<Size> iterate = sizes.iterator();

System.out.print("EnumSet: ");
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
EnumSet: SMALL, MEDIUM, LARGE, EXTRALARGE

注意:

  • hasNext() - 如果枚举集中存在下一个元素,则返回true
  • next() - 返回枚举集中的下一个元素

remove

  • remove() - 从枚举集中删除指定的元素
  • removeAll() - 从枚举集中删除所有元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.EnumSet;

class Main {

enum Size {
SMALL, MEDIUM, LARGE, EXTRALARGE
}

public static void main(String[] args) {

// Creating EnumSet using allOf()
EnumSet<Size> sizes = EnumSet.allOf(Size.class);
System.out.println("EnumSet: " + sizes);

// Using remove()
boolean value1 = sizes.remove(Size.MEDIUM);
System.out.println("Is MEDIUM removed? " + value1);

// Using removeAll()
boolean value2 = sizes.removeAll(sizes);
System.out.println("Are all elements removed? " + value2);
}
}

输出:

1
2
3
EnumSet: [SMALL, MEDIUM, LARGE, EXTRALARGE]
Is MEDIUM removed? true
Are all elements removed? true

其它方法

Method Description
copyOf() 创建EnumSet的副本
contains() 在EnumSet中搜索指定的元素并返回布尔结果
isEmpty() 检查EnumSet是否为空
size() 返回EnumSet的大小
clear() 从EnumSet中删除所有元素

Clonable 和 Serializable 接口

EnumSet类还实现了CloneableSerializable接口。

Clonable

它允许EnumSet类制作该类实例的副本。

Serializable

每当需要通过网络传输Java对象时,就需要将对象转换为位或字节。这是因为Java对象无法通过网络传输。Serializable接口允许对类进行序列化。这意味着可以将实现Serializable的类的对象转换为位或字节。

EnumSet 好处

与其他set实现(例如HashSetTreeSet)相比,EnumSet提供了一种存储枚举值的有效方法。

枚举集仅存储特定枚举的枚举值。因此,JVM已经知道该集合的所有可能值。

这就是为什么枚举集在内部被实现为一系列Bits的原因。Bits指定元素是否存在于枚举集中。

如果集合中存在该元素,则将其对应的位打开。

LinkedHashSet

Javacollections frameworkLinkedHashSet类提供了哈希表和链表数据结构的功能。

LinkedHashSet的元素存储在类似于HashSet的哈希表中

但是,LinkedHashSet在内部为其所有元素维护一个双链表。链表定义了在哈希表中插入元素的顺序。

创建 LinkedHashSet

为了创建链接的哈希集,我们必须首先导入java.util.LinkedHashSet包。

1
2
// LinkedHashSet with 8 capacity and 0.75 load factor
LinkedHashSet<Integer> numbers = new LinkedHashSet<>(8, 0.75);

注意,新的LinkedHashSet <>(8,0.75)部分。在这里,第一个参数是容量,第二个参数是负载系数。

  • capacity - 该哈希集的容量为8。意味着,它可以存储8个元素。
  • loadFactor - 此哈希集的负载系数为0.6。这意味着,只要我们的哈希表填充了60%,元素就会移到新哈希表中,其大小是原始哈希表的两倍。

注意:capacityloadFactor默认值分别是 16,0.75;

LinkedHashSet 中的方法

LinkedHashSet类提供的方法使我们可以对链表的哈希集执行各种操作。

插入元素

  • add() - 将指定的元素插入到链表的哈希集中
  • addAll() - 将指定集合的所有元素插入到链接的哈希集中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> evenNumber = new LinkedHashSet<>();

// Using add() method
evenNumber.add(2);
evenNumber.add(4);
evenNumber.add(6);
System.out.println("LinkedHashSet: " + evenNumber);

LinkedHashSet<Integer> numbers = new LinkedHashSet<>();

// Using addAll() method
numbers.addAll(evenNumber);
numbers.add(5);
System.out.println("New LinkedHashSet: " + numbers);
}
}

输出:

1
2
LinkedHashSet: [2, 4, 6]
New LinkedHashSet: [2, 4, 6, 5]

获取元素

要访问链表的哈希集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.LinkedHashSet;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("LinkedHashSet: " + numbers);

// Calling the iterator() method
Iterator<Integer> iterate = numbers.iterator();

System.out.print("LinkedHashSet using Iterator: ");

// Accessing elements
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
LinkedHashSet: [2, 5, 6]
LinkedHashSet using Iterator: 2, 5, 6,

注意:

  • hasNext() - 如果LinkedHashSet中存在下一个元素,则返回true.
  • next() - 返回LinkedHashSet中的下一个元素

移除元素

  • remove() - 从LinkedHashSet中删除指定的元素
  • removeAll() -从LinkedHashSet中删除所有的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("LinkedHashSet: " + numbers);

// Using the remove() method
boolean value1 = numbers.remove(5);
System.out.println("Is 5 removed? " + value1);

boolean value2 = numbers.removeAll(numbers);
System.out.println("Are all elements removed? " + value2);
}
}

输出:

1
2
3
LinkedHashSet: [2, 5, 6]
Is 5 removed? true
Are all elements removed? true

Set 操作符

LinkedHashSet类的各种方法也可以用于执行各种集合操作。

Union

两个执行两个集合之间的联合,我们可以使用addAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("LinkedHashSet1: " + evenNumbers);

LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
numbers.add(1);
numbers.add(3);
System.out.println("LinkedHashSet2: " + numbers);

// Union of two set
numbers.addAll(evenNumbers);
System.out.println("Union is: " + numbers);
}
}

输出:

1
2
3
LinkedHashSet1: [2, 4]
LinkedHashSet2: [1, 3]
Union is: [1, 3, 2, 4]

Intersection

为了执行两个集合之间的交集,我们可以使用retainAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("LinkedHashSet1: " + primeNumbers);

LinkedHashSet<Integer> evenNumbers = new LinkedHashSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("LinkedHashSet2: " + evenNumbers);

// Intersection of two sets
evenNumbers.retainAll(primeNumbers);
System.out.println("Intersection is: " + evenNumbers);
}
}

输出:

1
2
3
LinkedHashSet1: [2, 3]
LinkedHashSet2: [2, 4]
Intersection is: [2]

Difference

要计算两组之间的差异,我们可以使用removeAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
primeNumbers.add(5);
System.out.println("LinkedHashSet1: " + primeNumbers);

LinkedHashSet<Integer> oddNumbers = new LinkedHashSet<>();
oddNumbers.add(1);
oddNumbers.add(3);
oddNumbers.add(5);
System.out.println("LinkedHashSet2: " + oddNumbers);

// Difference between LinkedHashSet1 and LinkedHashSet2
primeNumbers.removeAll(oddNumbers);
System.out.println("Difference : " + primeNumbers);
}
}

输出:

1
2
3
LinkedHashSet1: [2, 3, 5]
LinkedHashSet2: [1, 3, 5]
Difference: [2]

Subset

为了检查一个集合是否是另一个集合的子集,我们可以使用containsAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.LinkedHashSet;

class Main {
public static void main(String[] args) {
LinkedHashSet<Integer> numbers = new LinkedHashSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("LinkedHashSet1: " + numbers);

LinkedHashSet<Integer> primeNumbers = new LinkedHashSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("LinkedHashSet2: " + primeNumbers);

// Check if primeNumbers is a subset of numbers
boolean result = numbers.containsAll(primeNumbers);
System.out.println("Is LinkedHashSet2 is subset of LinkedHashSet1? " + result);
}
}

输出:

1
2
3
LinkedHashSet1: [1, 2, 3, 4]
LinkedHashSet2: [2, 3]
Is LinkedHashSet2 is a subset of LinkedHashSet1? true

LinkedHashSet其它方法

Method Description
clone() 创建 LinkedHashSet副本
contains() LinkedHashSet中搜索指定的元素,并返回布尔结果
isEmpty() 检查LinkedHashSet是否为空
size() 返回`LinkedHashSet的大小
clear() LinkedHashSet中删除所有元素

LinkedHashSet Vs. HashSet

LinkedHashSet和HashSet都实现Set接口。但是,它们之间存在一些差异。

  • LinkedHashSet在内部维护一个链表。因此,它保持其元素的插入顺序。
  • LinkedHashSet类比HashSet需要更多的存储空间。这是因为LinkedHashSet在内部维护链接列表。
  • LinkedHashSet的性能比HashSet慢。这是因为LinkedHashSet中存在链表。

LinkedHashSet Vs. TreeSet

这是LinkedHashSetTreeSet之间的主要区别:

  • TreeSet类实现SortedSet接口。
  • TreeSet通常比LinkedHashSet慢。这是因为每当元素添加到TreeSet时,它都必须执行排序操作。
  • LinkedHashSet允许插入空值。但是,我们不能将空值插入`TreeSet。

SortedSet

Java collections frameworkSortedSet接口用于将元素以某种顺序存储在集合中。

实现SortedSet的类

为了使用SortedSet接口的功能,我们需要使用实现该接口的TreeSet类。

怎么使用 SortedSet

要使用SortedSet,我们必须首先导入java.util.SortedSet包。

1
2
// SortedSet implementation by TreeSet class
SortedSet<String> animals = new TreeSet<>();

在这里,我们没有使用任何参数来创建排序集。因此,该集合将自然排序。

SortedSet中的方法

SortedSet接口包含Set接口的所有方法。这是因为SetSortedSet的超级接口。

除了Set接口中包含的方法外,SortedSet接口还包括以下方法:

  • comparator() - 返回一个比较器,该比较器可用于对集合中的元素进行排序
  • first() - 返回集合的第一个元素
  • last() - 返回集合的最后一个元素
  • headSet(element) - 返回指定元素之前的所有元素
  • tailSet(element) - 在指定元素之后(包括指定元素)返回集合中的所有元素
  • subSet(element1, element2) - 返回element1和element2之间的所有元素,包括element1

实现SortedSet的类 TreeSet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.SortedSet;
import java.util.TreeSet;

class Main {

public static void main(String[] args) {
// Creating SortedSet using the TreeSet
SortedSet<Integer> numbers = new TreeSet<>();

// Insert elements to the set
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("SortedSet: " + numbers);

// Access the element
int firstNumber = numbers.first();
System.out.println("First Number: " + firstNumber);

int lastNumber = numbers.last();
System.out.println("Last Number: " + lastNumber);

// Remove elements
boolean result = numbers.remove(2);
System.out.println("Is the number 2 removed? " + result);
}
}

输出:

1
2
3
4
SortedSet: [1, 2, 3, 4]
First Number: 1
Last Number: 4
Is the number 2 removed? true

Java Collections frameworkNavigableSet接口提供了在集合之间导航的功能。

实现NavigableSet的类

为了使用NavigableSet接口的功能,我们需要使用实现NavigableSetTreeSet类。

怎么使用 NavigableSet

在Java中,我们必须导入java.util.NavigableSet包才能使用NavigableSet

1
2
// SortedSet implementation by TreeSet class
NavigableSet<String> numbers = new TreeSet<>();

NavigableSet被视为SortedSet的一种。这是因为NavigableSet扩展了SortedSet接口。

但是,在NavigableSet中,对SortedSet的某些方法(headSet()tailSet()subSet())进行了不同的定义。

headSet(element, booleanValue)

headSet()方法返回指定元素之前的可导航集合的所有元素(作为参数传递)。booleanValue参数是可选的。其默认值为false。如果将true作为booleanValue传递,则该方法返回指定元素之前的所有元素,包括指定元素。

tailSet(element, booleanValue)

tailSet()方法在包含指定元素的指定元素(作为参数传递)之后返回可导航集中的所有元素。

booleanValue参数是可选的。其默认值为true

如果将false作为booleanValue传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。

subSet(e1,bv1,e2,bv2)

subSet()方法返回e1e2之间的所有元素,包括e1

bv1bv2是可选参数。 bv1的默认值为truebv2的默认值为false

如果将false作为bv1传递,则该方法返回e1e2之间的所有元素,而不包括e1

如果将true作为bv2传递,则该方法返回e1e2之间的所有元素,包括e1

NavigableSet提供了各种可用于导航其元素的方法。

  • descendingSet() - 反转集合中元素的顺序
  • descendingIterator() - 返回一个迭代器,该迭代器可用于以相反的顺序迭代集合
  • ceiling() - 返回大于或等于指定元素的那些元素中的最低元素
  • floor() - 返回小于或等于指定元素的那些元素中最大的元素
  • higher() - 返回大于指定元素的那些元素中的最低元素
  • lower() - 返回小于指定元素的那些元素中最大的元素
  • pollFirst() - 返回并从集合中删除第一个元素
  • pollLast() - 返回并从集合中删除最后一个元素

实现 NavigableSet接口的类TreeSet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.NavigableSet;
import java.util.TreeSet;

class Main {

public static void main(String[] args) {
// Creating NavigableSet using the TreeSet
NavigableSet<Integer> numbers = new TreeSet<>();

// Insert elements to the set
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("NavigableSet: " + numbers);

// Access the first element
int firstElement = numbers.first();
System.out.println("First Number: " + firstElement);

// Access the last element
int lastElement = numbers.last();
System.out.println("Last Element: " + lastElement);

// Remove the first element
int number1 = numbers.pollFirst();
System.out.println("Removed First Element: " + number1);

// Remove the last element
int number2 = numbers.pollLast();
System.out.println("Removed Last Element: " + number2);

}
}

输出:

1
2
3
4
5
NavigableSet: [1, 2, 3]
First Element: 1
Last Element: 3
Removed First Element: 1
Removed Last Element: 3

TreeSet

Java collections frameworkTreeSet类提供树数据结构的功能。

创建 TreeSet

为了创建树集,我们必须首先导入java.util.TreeSet包。

1
TreeSet<Integer> numbers = new TreeSet<>();

在这里,我们创建了一个不带任何参数的TreeSet。在这种情况下,TreeSet中的元素会自然排序(升序)。

但是,我们可以使用Comparator接口自定义元素的排序。

TreeSet中的方法

TreeSet类提供了各种方法,使我们可以对集合执行各种操作。

插入元素

  • add() - 将指定的元素插入集合
  • addAll() - 将指定集合的所有元素插入集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeSet;

class Main {
public static void main(String[] args) {

TreeSet<Integer> evenNumbers = new TreeSet<>();

// Using the add() method
evenNumbers.add(2);
evenNumbers.add(4);
evenNumbers.add(6);
System.out.println("TreeSet: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);

// Using the addAll() method
numbers.addAll(evenNumbers);
System.out.println("New TreeSet: " + numbers);
}
}

输出:

1
2
TreeSet: [2, 4, 6]
New TreeSet: [1, 2, 4, 6]

获取元素

要访问树集的元素,我们可以使用iterator()方法。为了使用此方法,我们必须导入java.util.Iterator包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeSet;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Calling iterator() method
Iterator<Integer> iterate = numbers.iterator();
System.out.print("TreeSet using Iterator: ");
// Accessing elements
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出:

1
2
TreeSet: [2, 5, 6]
TreeSet using Iterator: 2, 5, 6,

删除元素

  • remove() - 从集合中移除指定的元素
  • removeAll() - 从集合中删除所有元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using the remove() method
boolean value1 = numbers.remove(5);
System.out.println("Is 5 removed? " + value1);

// Using the removeAll() method
boolean value2 = numbers.removeAll(numbers);
System.out.println("Are all elements removed? " + value2);
}
}

输出:

1
2
3
TreeSet: [2, 5, 6]
Is 5 removed? true
Are all elements removed? true

由于TreeSet类实现了NavigableSet,因此它提供了各种方法来浏览树集的元素。

first() and last()

  • first() - 返回集合的第一个元素
  • last() - 返回集合的最后一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using the first() method
int first = numbers.first();
System.out.println("First Number: " + first);

// Using the last() method
int last = numbers.last();
System.out.println("Last Number: " + last);
}
}

输出:

1
2
3
TreeSet: [2, 5, 6]
First Number: 2
Last Number: 6

ceiling(), floor(), higher() and lower()

  • higher(element) - 返回大于指定元素的那些元素中的最低元素
  • lower(element) - 返回小于指定元素的那些元素中最大的元素
  • ceiling(element) - 返回大于指定元素的那些元素中的最低元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
  • floor(element) - 返回小于指定元素的那些元素中最大的元素, 如果传递的元素存在于树集中,则返回作为参数传递的元素.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using higher()
System.out.println("Using higher: " + numbers.higher(4));

// Using lower()
System.out.println("Using lower: " + numbers.lower(4));

// Using ceiling()
System.out.println("Using ceiling: " + numbers.ceiling(4));

// Using floor()
System.out.println("Using floor: " + numbers.floor(3));

}
}

输出:

1
2
3
4
5
TreeSet: [2, 4, 5, 6]
Using higher: 5
Using lower: 2
Using ceiling: 4
Using floor: 2

pollfirst() and pollLast()

  • pollFirst() - 返回并从集合中删除第一个元素
  • pollLast() - 返回并从集合中删除最后一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using pollFirst()
System.out.println("Removed First Element: " + numbers.pollFirst());

// Using pollLast()
System.out.println("Removed Last Element: " + numbers.pollLast());

System.out.println("New TreeSet: " + numbers);
}
}

输出:

1
2
3
4
TreeSet: [2, 4, 5, 6]
Removed First Element: 2
Removed Last Element: 6
New TreeSet: [4, 5]

headSet(element, booleanValue)

headSet()方法返回指定元素(作为参数传递)之前的树集的所有元素。booleanValue参数是可选的。其默认值为false

如果将true作为booleanValue传递,则该方法返回指定元素之前的所有元素,包括指定元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using headSet() with default boolean value
System.out.println("Using headSet without boolean value: " + numbers.headSet(5));

// Using headSet() with specified boolean value
System.out.println("Using headSet with boolean value: " + numbers.headSet(5, true));
}
}

输出:

1
2
3
TreeSet: [2, 4, 5, 6]
Using headSet without boolean value: [2, 4]
Using headSet with boolean value: [2, 4, 5]

tailSet(element, booleanValue)

tailSet()方法返回包含指定元素的指定元素(作为参数传递)之后的树集的所有元素.booleanValue参数是可选的。其默认值为true

如果将false作为booleanValue传递,则该方法返回指定元素之后的所有元素,而不包括指定元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using tailSet() with default boolean value
System.out.println("Using tailSet without boolean value: " + numbers.tailSet(4));

// Using tailSet() with specified boolean value
System.out.println("Using tailSet with boolean value: " + numbers.tailSet(4, false));
}
}

输出:

1
2
3
TreeSet: [2, 4, 5, 6]
Using tailSet without boolean value: [4, 5, 6]
Using tailSet with boolean value: [5, 6]

subSet(e1, bv1, e2, bv2)

subSet()方法返回e1e2之间的所有元素,包括e1

bv1bv2是可选参数。 bv1的默认值为truebv2的默认值为false

如果将false作为bv1传递,则该方法返回e1e2之间的所有元素,而不包括e1

如果将true作为bv2传递,则该方法返回e1e2之间的所有元素,包括e1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// Using subSet() with default boolean value
System.out.println("Using subSet without boolean value: " + numbers.subSet(4, 6));

// Using subSet() with specified boolean value
System.out.println("Using subSet with boolean value: " + numbers.subSet(4, false, 6, true));
}
}

输出:

1
2
3
TreeSet: [2, 4, 5, 6]
Using subSet without boolean value: [4, 5]
Using subSet with boolean value: [5, 6]

集合操作符

TreeSet类的方法还可用于执行各种集合操作。

Union

为了执行两个集合之间的联合,我们使用addAll()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("TreeSet2: " + numbers);

// Union of two sets
numbers.addAll(evenNumbers);
System.out.println("Union is: " + numbers);

}
}

输出:

1
2
3
TreeSet1: [2, 4]
TreeSet2: [1, 2, 3]
Union is: [1, 2, 3, 4]
Intersection

为了执行两个集合之间的交集,我们使用了retainAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("TreeSet2: " + numbers);

// Intersection of two sets
numbers.retainAll(evenNumbers);
System.out.println("Intersection is: " + numbers);
}
}

输出:

1
2
3
TreeSet1: [2, 4]
TreeSet2: [1, 2, 3]
Intersection is: [2]

Difference

要计算两组之间的差异,我们可以使用removeAll()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("TreeSet2: " + numbers);

// Difference between two sets
numbers.removeAll(evenNumbers);
System.out.println("Difference is: " + numbers);
}
}

输出:

1
2
3
TreeSet1: [2, 4]
TreeSet2: [1, 2, 3, 4]
Difference is: [1, 3]

Subset

要检查一个集合是否是另一个集合的子集,我们使用containsAll()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("TreeSet1: " + numbers);

TreeSet<Integer> primeNumbers = new TreeSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("TreeSet2: " + primeNumbers);

// Check if primeNumbers is subset of numbers
boolean result = numbers.containsAll(primeNumbers);
System.out.println("Is TreeSet2 subset of TreeSet1? " + result);
}
}

输出:

1
2
3
TreeSet1: [1, 2, 3, 4]
TreeSet2: [2, 3]
Is TreeSet2 subset of TreeSet1? True

TreeSet中其它方法

Method Description
clone() 创建TreeSet的副本
contains() 在TreeSet中搜索指定的元素并返回布尔结果
isEmpty() 检查TreeSet是否为空
size() 返回TreeSet的大小
clear() 从TreeSet中删除所有元素

TreeSet Vs. HashSet

TreeSet和HashSet都实现Set接口。但是,它们之间存在一些差异。

  • HashSet不同,TreeSet中的元素以某种顺序存储。这是因为TreeSet也实现了SortedSet接口。
  • TreeSet提供了一些易于导航的方法。例如first()last()headSet()tailSet()等。这是因为TreeSet还实现了NavigableSet接口。
  • HashSet比TreeSet快,对于诸如addremovecontainssize之类的基本操作。

TreeSet Comparator

我们可以自定义元素的顺序。为此,我们需要基于对树集中的哪些元素进行排序来创建自己的Comparator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.TreeSet;
import java.util.Comparator;

class Main {
public static void main(String[] args) {

// Creating a tree set with customized comparator
TreeSet<String> animals = new TreeSet<>(new CustomComparator());

animals.add("Dog");
animals.add("Zebra");
animals.add("Cat");
animals.add("Horse");
System.out.println("TreeSet: " + animals);
}

// Creating a comparator class
public static class CustomComparator implements Comparator<String> {

@Override
public int compare(String animal1, String animal2) {
int value = animal1.compareTo(animal2);

// elements are sorted in reverse order
if (value > 0) {
return -1;
}
else if (value < 0) {
return 1;
}
else {
return 0;
}
}
}
}

输出:

1
TreeSet: [Zebra, Horse, Dog, Cat]

在上面的示例中,我们创建了一个树集,将CustomComparator类作为参数传递。

CustomComparator类实现Comparator接口

然后,我们重写compare()方法。现在,该方法将以相反的顺序对元素进行排序.

Iterator

Java collection frameworkIterator接口允许我们访问集合的元素。它具有一个子接口ListIterator

所有Java集合都包含iterator()方法。此方法返回用于迭代集合元素的迭代器实例。

Iterator 中的方法

Iterator接口提供了4种方法,可用于对集合元素执行各种操作。

  • hasNext() - 如果集合中存在一个元素,则返回true
  • next() - 返回集合的下一个元素
  • remove() - 删除next()返回的最后一个元素
  • forEachRemaining() - 对集合的每个剩余元素执行指定的操作

例子🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.ArrayList;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(3);
numbers.add(2);
System.out.println("ArrayList: " + numbers);

// Creating an instance of Iterator
Iterator<Integer> iterate = numbers.iterator();

// Using the next() method
int number = iterate.next();
System.out.println("Accessed Element: " + number);

// Using the remove() method
iterate.remove();
System.out.println("Removed Element: " + number);

System.out.print("Updated ArrayList: ");

// Using the hasNext() method
while(iterate.hasNext()) {
// Using the forEachRemaining() method
iterate.forEachRemaining((value) -> System.out.print(value + ", "));
}
}
}

输出:

1
2
3
4
ArrayList: [1, 3, 2]
Acessed Element: 1
Removed Element: 1
Updated ArrayList: 3, 2,

在上面的示例中

1
iterate.forEachRemaining((value) -> System.put.print(value + ", "));

在这里,我们将lambda表达式作为forEachRemaining()方法的参数传递。现在,该方法将打印数组列表中的所有其余元素。

ListIterator

Java collection framework ListIterator接口提供了访问list元素的功能.它是双向的。这意味着它允许我们在两个方向上迭代列表的元素。

List接口提供了一个ListIterator()方法,该方法返回ListIterator 接口的一个实例。

ListIterator中的方法

  • hasNext() - 如果列表中存在一个元素,则返回true
  • next() - 返回列表的下一个元素
  • nextIndex() - 返回下个元素的索引.(调用next()方法获取的元素)
  • previous() - 返回列表的上一个元素
  • previousIndex() - 返回列表的上一个元素索引(调用previousIndex()方法获取的元素)
  • remove() - 删除由next()previous()返回的元素
  • set() - 将next()previous()返回的元素替换为指定的元素

例子🌰1

在下面的示例中,我们在数组列表中实现了ListIterator接口的next()nextIndex()hasNext()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.ArrayList;
import java.util.ListIterator;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(3);
numbers.add(2);
System.out.println("ArrayList: " + numbers);

// Creating an instance of ListIterator
ListIterator<Integer> iterate = numbers.listIterator();

// Using the next() method
int number1 = iterate.next();
System.out.println("Next Element: " + number1);

// Using the nextIndex()
int index1 = iterate.nextIndex();
System.out.println("Position of Next Element: " + index1);

// Using the hasNext() method
System.out.println("Is there any next element? " + iterate.hasNext());
}
}

输出:

1
2
3
4
ArrayList: [1, 3, 2]
Next Element: 1
Position of Next Element: 1
Is there any next element? true

例子🌰2

在下面的示例中,我们在数组列表中实现了ListIterator接口的previous()previousIndex()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.ArrayList;
import java.util.ListIterator;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(3);
numbers.add(2);
System.out.println("ArrayList: " + numbers);

// Creating an instance of ListIterator
ListIterator<Integer> iterate = numbers.listIterator();
iterate.next();
iterate.next();

// Using the previous() method
int number1 = iterate.previous();
System.out.println("Previous Element: " + number1);

// Using the previousIndex()
int index1 = iterate.previousIndex();
System.out.println("Position of the Previous element: " + index1);
}
}

输出:

1
2
3
ArrayList: [1, 3, 2]
Previous Element: 3
Position of the Previous Element: 0

在上面的示例中,最初,Iterator的实例在1之前。由于在1之前没有元素,因此调用previous()方法将引发异常。

然后,我们使用了next()方法两次。现在,Iterator实例将在3到2之间。因此,previous()方法返回3。

Java中算法

Java collection framework提供了各种算法,可用于处理存储在数据结构中的元素。

Java中的算法是静态方法,可用于对集合执行各种操作。

由于算法可以用于各种集合,因此也称为通用算法。

使用sort()排序

sort()方法用于对元素进行排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayList;
import java.util.Collections;

class Main {
public static void main(String[] args) {

// Creating an array list
ArrayList<Integer> numbers = new ArrayList<>();

// Add elements
numbers.add(4);
numbers.add(2);
numbers.add(3);
System.out.println("Unsorted ArrayList: " + numbers);

// Using the sort() method
Collections.sort(numbers);
System.out.println("Sorted ArrayList: " + numbers);

}
}

输出:

1
2
Unsorted ArrayList: [4, 2, 3]
Sorted ArrayList: [2, 3, 4]

在此,排序以自然顺序(升序)进行。但是,我们可以使用Comparator接口自定义sort()方法的排序顺序。

随机排序shuffle()

shuffle()方法用于破坏数据结构中存在的任何种类的顺序,它与排序相反。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.ArrayList;
import java.util.Collections;

class Main {
public static void main(String[] args) {

// Creating an array list
ArrayList<Integer> numbers = new ArrayList<>();

// Add elements
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("Sorted ArrayList: " + numbers);

// Using the shuffle() method
Collections.shuffle(numbers);
System.out.println("ArrayList using shuffle: " + numbers);

}
}

输出:

1
2
Sorted ArrayList: [1, 2, 3]
ArrayList using shuffle: [2, 1, 3]

当我们运行程序时,shuffle()方法将返回随机输出。

常规数据操作

在Java中,collections framework提供了可用于处理数据的不同方法。

  • reverse() - 反转元素的顺序
  • fill() - 用指定值替换集合中的每个元素
  • copy() - 创建从指定源到目标的元素副本
  • swap() - 交换集合中两个元素的位置
  • addAll() - 将一个集合的所有元素添加到其他集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.Collections;
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
System.out.println("ArrayList1: " + numbers);

// Using reverse()
Collections.reverse(numbers);
System.out.println("Reversed ArrayList1: " + numbers);

// Using swap()
Collections.swap(numbers, 0, 1);
System.out.println("ArrayList1 using swap(): " + numbers);

ArrayList<Integer> newNumbers = new ArrayList<>();

// Using addAll
newNumbers.addAll(numbers);
System.out.println("ArrayList2 using addAll(): " + newNumbers);

// Using fill()
Collections.fill(numbers, 0);
System.out.println("ArrayList1 using fill(): " + numbers);

// Using copy()
Collections.copy(newNumbers, numbers);
System.out.println("ArrayList2 using copy(): " + newNumbers);
}
}

输出:

1
2
3
4
5
6
ArrayList1: [1, 2]
Reversed ArrayList1: [2, 1]
ArrayList1 Using swap(): [1, 2]
ArrayList2 using addALl(): [1, 2]
ArrayList1 using fill(): [0, 0]
ArrayList2 using copy(): [0, 0]

注意:在执行copy()方法时,两个列表的大小应相同。

使用binarySearch()搜索

binarySearch()方法搜索指定的元素。它返回元素在指定集合中的位置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.Collections;
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);

// Using binarySearch()
int pos = Collections.binarySearch(numbers, 3);
System.out.println("The position of 3 is " + pos);
}
}

输出:

1
The position of 3 is 2.

注意:应该在执行binarySearch()方法之前对集合进行排序。

Composition

  • frequency() - 返回元素在集合中存在的次数
  • disjoint() - 检查两个集合是否不相交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.Collections;
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(2);
System.out.println("ArrayList1: " + numbers);

int count = Collections.frequency(numbers, 2);
System.out.println("Count of 2: " + count);

ArrayList<Integer> newNumbers = new ArrayList<>();
newNumbers.add(5);
newNumbers.add(6);
System.out.println("ArrayList2: " + newNumbers);

boolean value = Collections.disjoint(numbers, newNumbers);
System.out.println("Two lists are disjoint: " + value);
}
}

输出:

1
2
3
4
ArrayList1: [1, 2, 3, 2]
Count of 2: 2
ArrayList2: [5, 6]
Two lists are disjoint: true

寻找极限值

Java collections framework min()max()方法分别用于查找最小和最大元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Collections;
import java.util.ArrayList;

class Main {
public static void main(String[] args) {
// Creating an ArrayList
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);

// Using min()
int min = Collections.min(numbers);
System.out.println("Minimum Element: " + min);

// Using max()
int max = Collections.max(numbers);
System.out.println("Maximum Element: " + max);
}
}

输出:

1
2
Minimum Element: 1
Maximum Element: 3