文章目录
-
- 一、创建不可变的集合
-
- 1.1为什么创建不可变的集合
- [1.2 创建List、Set和Map的不可变集合](#1.2 创建List、Set和Map的不可变集合)
-
- [1.2.1 创建List的不可变集合](#1.2.1 创建List的不可变集合)
- [1.2.2 创建Set 的不可变集合](#1.2.2 创建Set 的不可变集合)
- [1.2.3 创建Map的不可变集合](#1.2.3 创建Map的不可变集合)
- [二、使用集合 的Stream 流](#二、使用集合 的Stream 流)
-
- [2.1 Stream的使用步骤](#2.1 Stream的使用步骤)
- [2.2 Stream的方法](#2.2 Stream的方法)
- [三、如何获取Stream 流对象](#三、如何获取Stream 流对象)
- [四、练习使用集合的Stream 流](#四、练习使用集合的Stream 流)
一、创建不可变的集合
1.1为什么创建不可变的集合
- 不可变集合是线程安全的,因为它们的状态在创建后不会改变。多个线程可以安全地共享和读取不可变集合,而无需同步。
- 不可变集合不允许修改,可以安全地缓存和重用
- 在多线程环境下使用 Stream 时,确保没有其他线程修改源集合
1.2 创建List、Set和Map的不可变集合
1.2.1 创建List的不可变集合
-
方式一
public class Demo09 {
public static void main(String[] args) {
// 创建不可变的List集合
List<String> list = List.of("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");// 增强for 循环 遍历 for (String s : list){ System.out.println(s); } // 迭代器 遍历 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } list.set(0,"张三"); // 集合不可修改,会报异常 }
}
-
方式二
public class Demo09 {
public static void main(String[] args) {
List<String> list = Arrays.asList("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");
List<String> immutableList = Collections.unmodifiableList(list); // 设置不可变// 增强for 循环 遍历 for (String s : immutableList){ System.out.println(s); } // 迭代器 遍历 Iterator<String> iterator = immutableList.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } immutableList.set(0,"张三"); // 集合不可修改会报异常 }
}
1.2.2 创建Set 的不可变集合
public class Demo09 {
public static void main(String[] args) {
// 创建 Set 的不可变集合
Set<String> set = Set.of("张飞","关羽","刘备","曹操","孙权","孙尚香","吕布");
// 增强for 循环遍历
for (String s : set){
System.out.println(s);
}
// 迭代器遍历
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
set.add("诸葛亮"); // 不可变,报异常
}
}
1.2.3 创建Map的不可变集合
-
初版,不建议
public class Demo09 {
public static void main(String[] args) {
// 创建 Map的不可变集合 最多十个键值对,一般不用这种方式
Map<String,Object> map1 = Map.of("姓名","张三","年龄",25,"地址","北京");// 创建不可变的Map 集合,元素个数不限 Map<String,Object> map = new HashMap<>(); map.put("姓名","李四"); map.put("年龄",25); map.put("地址","北京"); Set<Map.Entry<String,Object>> entrySet = map.entrySet(); Map.Entry[] arr1 = new Map.Entry[0]; // 底层会比较 entrySet 和arr1 的长度 ,长度不够会创建新的数组 Map.Entry[] arrayEntry = entrySet.toArray(arr1); // Entry数组 Map<String,Object> immutableMap = Map.ofEntries(arrayEntry); // 不可变集合 immutableMap.put("工资",10000); // 不支持修改,报异常 }
}
-
使用copyOf ,建议
public class Demo09 {
public static void main(String[] args) {
// 创建 Map的不可变集合 最多十个键值对,一般不用这种方式
Map<String,Object> map1 = Map.of("姓名","张三","年龄",25,"地址","北京");// 创建不可变的Map 集合,元素个数不限 Map<String,Object> map = new HashMap<>(); map.put("姓名","李四"); map.put("年龄",25); map.put("地址","北京"); Map<String,Object> immutableMap = Map.copyOf(map); // 创建不可变的集合 // 遍历方式一 Set<String> ketSet = map.keySet(); for (String key:ketSet){ System.out.println(map.get(key)); } // 遍历方式二 Set<Map.Entry<String,Object>> entrySet = map.entrySet(); for (Map.Entry entry: entrySet ){ System.out.println(entry.getKey() + "=" + entry.getValue()); } immutableMap.put("工资",10000); // 不可变,报异常 }
}
二、使用集合 的Stream 流
2.1 Stream的使用步骤
获取到集合的Stream 流,相当于流水线 --> 把数据交给流处理 ,帅选,检查等 --> 流返回一个新的集合,流水线产品
- 获取Stream 对象
- 使用中间方法处理数据
- 使用终结方法处理数据
- 结合lambda表达式,简化操作
- 终结方法一旦被调用,stream对象也就不可用了
2.2 Stream的方法
- 常用处理方法(中间过程),返回Stream对象,链式调用
- 终结方法,用于遍历,统计、获取新的集合等,一经调用后Stream 对象就不可用了
三、如何获取Stream 流对象
- 单列集合(List/Set):使用stream方法
- 双列集合(Map):不能直接获取,需要转换成Set
- 数组:Arrays的静态方法stream
- 一堆零散的数据:Stream 接口的静态方法of
四、练习使用集合的Stream 流
-
案例一:统计集合中姓张的人数
public class Demo09 {
public static void main(String[] args) {
List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");long count = list.stream().filter(s->s.startsWith("张")) .count(); System.out.println("姓张的总人数:" + count); }
}
-
案例二:输出集合中所有姓张的人名
public class Demo09 {
public static void main(String[] args) {
List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");list.stream().filter(s->s.startsWith("张")) .forEach(s -> System.out.println(s)); }
}
-
案例三:输出前三个人的名字
public class Demo09 {
public static void main(String[] args) {
List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");list.stream().limit(3) .forEach(s -> System.out.println(s)); }
}
-
案例四:输出第四个人开始后面所有人的名字
public class Demo09 {
public static void main(String[] args) {
List<String> list = List.of("刘备","关羽","曹操","张飞","李四","张苞");list.stream().skip(3) .forEach(s -> System.out.println(s)); }
}
-
案例五:去除重复的人名
public class Demo09 {
public static void main(String[] args) {
List<String> list = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");list.stream().distinct() .forEach(s -> System.out.println(s)); }
}
-
案例六:合并两个集合
public class Demo09 {
public static void main(String[] args) {
List<String> list1 = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");List<String> list2 = List.of("王五","刘六"); Stream<String> stringStream = Stream.concat(list1.stream(),list2.stream()); stringStream.forEach(s -> System.out.println(s)); }
}
-
案例七:将集合的结果保存到数组中
public class Demo09 {
public static void main(String[] args) {
List<String> list1 = List.of("刘备","刘备","关羽","曹操","张飞","李四","张苞");Object[] objects = list1.stream() .distinct() .limit(3) .toArray(); for (Object o : objects){ System.out.println(o.toString()); } }
-
案例八:将Stream的处理结果放到集合中
public class Demo09 {
public static void main(String[] args) {
List<String> list1 = List.of("刘备", "刘备", "关羽", "曹操", "张飞", "李四", "张苞");// 方式一:不指定具体类型的数组
// Object[] objects = list1.stream()
// .distinct()
// .limit(3)
// .toArray();
// System.out.println(Arrays.toString(objects));// 方式二:指定类型的数组 String arr[] = list1.stream().toArray(new IntFunction<String[]>() { @Override public String[] apply(int value) { return new String[value]; } }); System.out.println(Arrays.toString(arr)); }
}
改成Lamda 表达式
public class Demo09 {
public static void main(String[] args) {
List<String> list1 = List.of("刘备", "刘备", "关羽", "曹操", "张飞", "李四", "张苞");
// 方式一:不指定具体类型的数组
// Object[] objects = list1.stream()
// .distinct()
// .limit(3)
// .toArray();
// System.out.println(Arrays.toString(objects));
// 方式二:指定类型的数组
String arr[] = list1.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(arr));
}
}
-
将数据收集到集合中
public class Demo09 {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
Collections.addAll(arrayList,"张三丰-男-99","周芷若-女-25","张无忌-男-21");
Collections.unmodifiableList(arrayList);// 设置为不可变的集合// 需求1:把所有的男性收集起来,放到一个List集合中
// List<String> newList = arrayList.stream().filter(new Predicate<String>() {
// @Override
// public boolean test(String s) {
// return s.contains("男");
// }
// }).collect(Collectors.toList());
// }// 需求2:把所有的男性收集起来,放到一个Set集合中
// Set<String> stringSet = arrayList.stream().filter(s -> s.contains("男"))
// .collect(Collectors.toSet());
// System.out.println(stringSet);/* 需求3:把所有的男性收集起来,放到一个Map集合中,姓名为键,年龄为值 toMap的两个参数:参数一:表示键的生成规则,参数二表示值的生成规则 Function<T, R>的两个参数,T 表示流的数据类型,即apply的参数类型;R表示返回的数据类型,即apply的返回类型 重要:键不能重复 */ Map<String,Integer> map = arrayList.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toMap(new Function<String, String>() { // 键的生成规则 @Override public String apply(String s) { return s.split("-")[0]; } }, new Function<String, Integer>() { // 值的生成规则 @Override public Integer apply(String s) { return Integer.parseInt(s.split("-")[2]); } })); System.out.println(map); }
}