Java集合概述

AI摘要:

概述

集合大致分为Set、List、Queue、和Map四种

  • Set - 无序不可重复的集合
  • List - 有序可重复的集合
  • Map - 具有映射关系的集合
  • Queue - 队列集合实现

泛型使集合可以记住容器中对象的类型

集合类主要由 Collection (Set、List、Queue)和 Map 根接口派生

Collection接口

以下是一些包含的方法(添加、删除、清空、个数等)

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.*;
public class CollectionTest
{
public static void main(String[] args)
{
Collection c = new ArrayList();
// 添加元素
c.add("孙悟空");
// 虽然集合里不能放基本类型的值,但Java支持自动装箱
c.add(6);
System.out.println("c集合的元素个数为:" + c.size()); // 输出2
// 删除指定元素
c.remove(6);
System.out.println("c集合的元素个数为:" + c.size()); // 输出1
// 判断是否包含指定字符串
System.out.println("c集合的是否包含\"孙悟空\"字符串:"
+ c.contains("孙悟空")); // 输出true
c.add("轻量级Java EE企业应用实战");
System.out.println("c集合的元素:" + c);
Collection books = new HashSet();
books.add("轻量级Java EE企业应用实战");
books.add("疯狂Java讲义");
System.out.println("c集合是否完全包含books集合?"
+ c.containsAll(books)); // 输出false
// 用c集合减去books集合里的元素
c.removeAll(books);
System.out.println("c集合的元素:" + c);
// 删除c集合里所有元素
c.clear();
System.out.println("c集合的元素:" + c);
// 控制books集合里只剩下c集合里也包含的元素
books.retainAll(c);
System.out.println("books集合的元素:" + books);
}
}

新方法 toArray(IntFunction) 可以返回特定类型的数组, 旧方法 toArray() 返回值总是 Object[]

IntFunction: 需要的数组类型加双冒号和new,即构造器引用

1
2
3
var strColl = List.of("Java", "Kotlin", "Swift", "Python");
String[] sa = strColl.toArray(String[]::new);
System.out.println(Arrays.toString(sa));

遍历集合

Lamdba表达式遍历集合

Collection 可以调用父接口 Iterable 的 forEach(Consumer action) 默认方法遍历集合元素

1
2
3
4
5
6
7
// 创建一个集合
Collection books = new HashSet();
books.add("轻量级Java EE企业应用实战");
books.add("疯狂Java讲义");
books.add("疯狂Android讲义");
// 调用forEach()方法遍历集合
books.forEach(obj -> System.out.println("迭代集合元素:" + obj));

Iterator遍历集合

Iterator 接口主要用于遍历,又称为迭代器

创建 Iterator 对象时,必须有一个被迭代的集合 Collection

方法

boolean hasnext() | Object next() | void remove()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 获取books集合对应的迭代器
Iterator it = books.iterator();
while(it.hasNext())
{
// it.next()方法返回的数据类型是Object类型,因此需要强制类型转换
String book = (String)it.next();
System.out.println(book);
if (book.equals("疯狂Java讲义"))
{
// 从集合中删除上一次next方法返回的元素
it.remove();
}
// 对book变量赋值,不会改变集合元素本身
book = "测试字符串"; //①
}

void forEachRemaining(Consumer action) : 可使用 Lambda 表达式遍历

1
2
3
Iterator it = books.iterator();
// 使用Lambda表达式(目标类型是Comsumer)来遍历集合元素
it.forEachRemaining(obj -> System.out.println("迭代集合元素:" + obj));

注意点

1
2
3
4
5
6
7
if (book.equals("疯狂Android讲义"))
{
// 使用Iterator迭代过程中,不可修改集合元素,下面代码引发异常
books.remove(book);
// 对book变量赋值,不会改变集合元素本身
book = "测试字符串"; //①
}

foreach 循环

1
2
3
4
5
6
7
8
9
10
11
for (Object obj : books)
{
// 此处的book变量也不是集合元素本身
String book = (String)obj;
System.out.println(book);
if (book.equals("疯狂Android讲义"))
{
// 下面代码会引发ConcurrentModificationException异常
books.remove(book); //①
}
}

操作集合

Predicate (谓词)

Collection 接口的 removeIf(Predicate filter) 方法,批量删除符合 filter 条件的元素,其中 Predicate 为函数式接口

1
2
3
4
5
6
7
8
9
10
11
import java.util.function.*;
// 创建一个集合
Collection books = new HashSet();
books.add(new String("轻量级Java EE企业应用实战"));
books.add(new String("疯狂Java讲义"));
books.add(new String("疯狂iOS讲义"));
books.add(new String("疯狂Ajax讲义"));
books.add(new String("疯狂Android讲义"));
// 使用Lambda表达式(目标类型是Predicate)过滤集合
books.removeIf(ele -> ((String)ele).length() < 10);
System.out.println(books);

实现更高需求的方法,定义一个额外的 calAll() 方法

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
public class PredicateTest2
{
public static void main(String[] args)
{
// 创建books集合、为books集合添加元素的代码与前一个程序相同。
Collection books = new HashSet();
books.add(new String("轻量级Java EE企业应用实战"));
books.add(new String("疯狂Java讲义"));
books.add(new String("疯狂iOS讲义"));
books.add(new String("疯狂Ajax讲义"));
books.add(new String("疯狂Android讲义"));
// 统计书名包含“疯狂”子串的图书数量
System.out.println(calAll(books , ele->((String)ele).contains("疯狂")));
// 统计书名包含“Java”子串的图书数量
System.out.println(calAll(books , ele->((String)ele).contains("Java")));
// 统计书名字符串长度大于10的图书数量
System.out.println(calAll(books , ele->((String)ele).length() > 10));
}
public static int calAll(Collection books , Predicate p)
{
int total = 0;
for (Object obj : books)
{
// 使用Predicate的test()方法判断该对象是否满足Predicate指定的条件
if (p.test(obj))
{
total ++;
}
}
return total;
}
}

Stream (流式API)

Stream 通用流接口 | IntStream、LongStream、DoubleStream 代表 int、long、double 的流

每个流式API都有对应的 Builder, 如 Stream.Builder

Stream 的使用步骤

  1. 使用 Stream 的 builder() 类方法创建对应的 Builder
  2. 调用 Builder 的 add() 方法添加元素
  3. 调用 Builder 的 build() 方法获取对应的 Stream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.stream.*;
IntStream is = IntStream.builder().add(20).add(13).add(-2).add(18).build();
// 下面调用聚集方法的代码每次只能执行一个
System.out.println("is所有元素的最大值:" + is.max().getAsInt());
System.out.println("is所有元素的最小值:" + is.min().getAsInt());
System.out.println("is所有元素的总和:" + is.sum());
System.out.println("is所有元素的总数:" + is.count());
System.out.println("is所有元素的平均值:" + is.average());
System.out.println("is所有元素的平方是否都大于20:" + is.allMatch(ele -> ele * ele > 20));
System.out.println("is是否包含任何元素的平方大于20:" + is.anyMatch(ele -> ele * ele > 20));
// 将is映射成一个新Stream,新Stream的每个元素是原Stream元素的2倍+1
IntStream newIs = is.map(ele -> ele * 2 + 1);
// 使用方法引用的方式来遍历集合元素
newIs.forEach(System.out::println); // 输出41 27 -3 37

Stream 的聚集方法

  • 中间方法:允许流保持打开状态,并允许直接调用后续方法
  • 末端方法:对流的最终操作,使流不再可用

Collection 的 stream() 方法

获取对应流,对集合元素批量操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 创建books集合、为books集合添加元素的代码与8.2.5小节的程序相同。
Collection books = new HashSet();
books.add(new String("轻量级Java EE企业应用实战"));
books.add(new String("疯狂Java讲义"));
books.add(new String("疯狂iOS讲义"));
books.add(new String("疯狂Ajax讲义"));
books.add(new String("疯狂Android讲义"));
// 统计书名包含“疯狂”子串的图书数量
System.out.println(books.stream()
.filter(ele->((String)ele).contains("疯狂"))
.count()); // 输出4
// 统计书名包含“Java”子串的图书数量
System.out.println(books.stream()
.filter(ele->((String)ele).contains("Java") )
.count()); // 输出2
// 统计书名字符串长度大于10的图书数量
System.out.println(books.stream()
.filter(ele->((String)ele).length() > 10)
.count()); // 输出2
// 先调用Collection对象的stream()方法将集合转换为Stream,
// 再调用Stream的mapToInt()方法获取原有的Stream对应的IntStream
books.stream().mapToInt(ele -> ((String)ele).length())
// 调用forEach()方法遍历IntStream中每个元素
.forEach(System.out::println);// 输出8 11 16 7 8

Java集合概述
https://blog.cngo.rr.nu/posts/fc73.html
作者
cngo
发布于
2024年8月11日
许可协议