11 Collection集合、Map集合:分类、功能、遍历、底层原理,Stream流:获取、中间方法、终结方法 (黑马Java视频笔记)

server/2025/3/18 10:19:38/

在这里插入图片描述

文章目录

    • 集合
      • 1. 认识集合
      • 2. Collection单列集合特点
      • 3. Collection单列集合的常用功能
      • 4. Collection的遍历方式
        • 1)迭代器遍历 Iterator
        • 2)增强for循环(for...each遍历)
        • 3)Lambda表达式:forEach()
      • 5. 三种遍历方式的区别
        • **5.1 并发修改异常问题**
        • **5.2 一般应对方案:**
        • 5.3 ⭐方案一:迭代器遍历并删除
          • 💡`modCount` 和 `expectedModCount` 的作用
        • 5.4 方案二:用增强for和Lambda都没有办法解决并发修改异常
      • 6. Collection-List集合:有序,可重复,有索引
        • 1) LIst集合因为支持索引,所以除了继承了Collection的功能外,还有很多与索引相关的方法
        • 2)遍历方式
        • 3)ArrayList和LinkedList的区别:
        • 4)LinkedList 应用场景:在首尾增删快
      • 7. Collection-Set系列集合:无序(添加顺序和获取顺序不一致)、不重复、无索引
        • 7.1 HashSet集合的底层原理
          • 1)哈希值
          • 2)对象哈希值的特点
          • 3)基于哈希表存储数据 >>> 无序、不重复、无索引
            • 存储方式变化过程:数组+链表 >>> 数组+链表+红黑树
            • 默认加载因子
          • 4)红黑树
          • 5)为什么性能好
        • 7.2 ⭐HashSet集合元素的去重操作 -> 自定义对象
          • 思考🤔🤔🤔
        • 7.3 LinkedHashSet集合的底层原理
          • **有序** → 每个元素都额外的多了一个**双链表**的机制记录它前后元素的位置
        • 7.4 TreeSet集合的原理
        • 7.5 什么时候用什么集合呢?
      • 8. Map集合(键值对集合)
        • 8.1 Map集合分类
        • 8.2 Map集合的常用方法
        • 8.3 Map集合的遍历方式
          • 1)键找值
          • 2)键值对
          • 3)Lambda表达式
        • 8.4 Map集合的实现类
          • 1)HashMap集合的底层原理
          • 2)LinkedHashMap的底层原理
          • 3)TreeMap的底层原理,同TreeSet集合
        • 8.5 Map集合的案例-统计投票信息
    • Stream流
      • 1. 获取Stream流
      • 2. 常用中间方法
      • 3. 常用终结方法
        • 3.1 常用终结方法
        • 3.2 收集Stream流:

集合

1. 认识集合

💡容器 >> 装数据

体系结构:

  • Collection 单列集合 :每个元素(数据)只包含一个值
  • Map 双列集合:每个元素包含两个值(键值对)

2. Collection单列集合特点

  • List系列集合
    • ArrayListLinekdList:添加的元素是有序、可重复、有索引
  • Set系列集合:添加的元素是无序、不重复、无索引
    • HashSet:无序、不重复、无索引
    • LinkedHashSet:有序、不重复、无索引
    • TreeSet:按照大小默认升序排序、不重复、无索引
java">public static void main(String[] args) {// 目标:搞清楚Collection集合的整体特点// 1、List家族的集合:有序、可重复、有索引List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");System.out.println(list);   // [张三, 李四, 王五]System.out.println(list.get(0));    // 张三// 2、Set家族的集合:无序、不可重复、无索引Set<String> set = new HashSet<>();set.add("张三");set.add("张三");set.add("李四");set.add("王五");System.out.println(set);    // [李四, 张三, 王五]System.out.println(set.contains("张三")); // true}

3. Collection单列集合的常用功能

  • Collection作为单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的

在这里插入图片描述

  • toArray方法的使用
java"> public static void main(String[] args) {Collection<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");System.out.println(list);   // [张三, 李四, 王五]// 把集合转换成数组:toArray() 默认转Object数组Object[] arr = list.toArray();System.out.println(arr.getClass()); // class [Ljava.lang.Object;System.out.println(Arrays.toString(arr));   // [张三, 李四, 王五]// 把集合转换成字符串数组String[] arr2 = list.toArray(String[]::new);// String[] arr2 = list.toArray(new String[0]);
/*      完整代码String[] arr3 = list.toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[0];}});
*/System.out.println(arr2.getClass());    // class [Ljava.lang.String;}

❓:具体询问ai理解

4. Collection的遍历方式

1)迭代器遍历 Iterator
  • 迭代器是用来遍历集合的专用方式(数组没有)

① 得到这个集合的迭代器对象

​ - 初始默认指在下标为0的位置

② 使用一个while循环来遍历

java">// 1. 迭代器遍历:Iterator
Collection<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");// 获取迭代器对象
Iterator<String> it = list.iterator();
while(it.hasNext()){System.out.println(it.next());
}
2)增强for循环(for…each遍历)
  • 即可以遍历数组,也可以遍历集合

    for (元素的数据类型 变量名:数组或者集合){ 
    }
    
java">for (String s : list) {System.out.println(s);
}
3)Lambda表达式:forEach()

在这里插入图片描述

java">// forEach本质上就是for增强遍历
default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}
}

5. 三种遍历方式的区别

5.1 并发修改异常问题
  • 如果在遍历集合的同时又存在增删集合元素的行为,可能会出现业务异常,这种现象被称之为并发修改异常问题
java">// list = [宁夏枸杞, 枸杞, 西洋参, 枸杞子, 红枣]
// 需求1:删除全部枸杞
for(int i=0;i<list.size();i++){String name = list.get(i);System.out.println(name);    // 只有List集合才有索引if(name.contains("枸杞")){list.remove(i);}
}
System.out.println(list);       // [枸杞, 西洋参, 红枣]

❓可以看到 list 集合中有一个遗漏的:这是因为在遍历到下标为 0 的 ” 宁夏枸杞 “ 时,i = 0 ,此时 ” 枸杞 “ 下标为 1,if 条件语句为 true → 删除下标为 0 的 ” 宁夏枸杞 “ ,” 枸杞 ” 的下标变为 0 ,“ 西洋参 ” 的下标变为 1 ,此时开始遍历 i = 1 的元素,不会遍历到 “ 枸杞 ”。

通过遍历时输出的 name ,也可以看到,并没有输出 “ 枸杞 ”

在这里插入图片描述

5.2 一般应对方案:
  • 在删除之后进行 i-- (编译器也会给出警告提示)

在这里插入图片描述

  • 倒着遍历并删除**(前提:支持索引)**
java">for(int i = list.size() - 1; i >= 0; i--){String name = list.get(i);System.out.println(name);if (name.contains("枸杞")) {list.remove(i);}
}
5.3 ⭐方案一:迭代器遍历并删除

使用迭代器来删除,而不是list集合删除(用list集合删除还是会存在并发修改异常)
迭代器内部会进行i--

java">// 迭代器遍历并删除
Iterator<String> it = list.iterator();while(it.hasNext()){String name = it.next();System.out.println(name);if(name.contains("枸杞")){it.remove();}
}
System.out.println(list);

⚠️如果使用迭代器遍历,使用集合方法删除 >> 报错!!!
在这里插入图片描述
🤔报错原因:modCount != expectedModCount,可以看到后台modCount = 6,expectedModCount = 5
在这里插入图片描述

💡modCountexpectedModCount 的作用

在这里插入图片描述

5.4 方案二:用增强for和Lambda都没有办法解决并发修改异常
  • 拿不到迭代器

  • 只适合做遍历,不适合做遍历并修改操作

6. Collection-List集合:有序,可重复,有索引

  • ArrayList:有序,可重复,有索引
  • LinkedList:有序,可重复,有索引
1) LIst集合因为支持索引,所以除了继承了Collection的功能外,还有很多与索引相关的方法

在这里插入图片描述

java">List<String> names = new ArrayList<>(); // 多态引用

在这里插入图片描述

java">List<String> names = new ArrayList<>();
// 1. 添加元素:add(E e)
names.add("张三");
names.add("李四");
names.add("王五");
System.out.println(names);// 根据下标添加元素:add(int index, E e)
names.add(1, "赵六");
System.out.println(names);// 2. 获取元素:get(int index)
String name = names.get(1);
System.out.println(name);// 3. 修改元素:set(int index, E e)
names.set(1, "赵六");
System.out.println(names);// 4. 删除元素:remove(int index)
names.remove(0);
System.out.println(names);// 5. 获取长度:size()
int size = names.size();
System.out.println(size);
2)遍历方式
  • for循环
java">for (int i = 0; i < names.size(); i++) {String name2 = names.get(i);System.out.println(name2);
}
  • 迭代器
java">Iterator<String> it = names.iterator();
while (it.hasNext()) {String name2 = it.next();System.out.println(name2);
}
  • 增强for
java">for (String name2 : names) {System.out.println(name2);
}
  • lambda表达式
java">names.forEach(System.out::println);// System.out::println 是一种 实例方法引用,它引用了 PrintStream 类的 println 方法。
// names.forEach(name2 -> System.out.println(name2));
3)ArrayList和LinkedList的区别:
  • ArrayList基于数组存储数据:连续存储区域 -> 根据索引查询数据较快,查询任意数据耗时与链表查询相同;增删数据效率低(扩容、迁移等)
  • LinkedList基于双链表存储数据:数据由结点组成,一个结点包含当前的数据值和下一个结点的地址(双链表的结点包含上一个结点地址和下一个结点地址),查询慢(需要从头开始找),增删相对快(不用迁移其他数据),但对首位元素进行增删改查的速度是极快的

在这里插入图片描述
在这里插入图片描述

4)LinkedList 应用场景:在首尾增删快
  • 设计队列:先进先出,后进后出 >>> 尾进头出
    • 入队:addLast
    • 出队:removeFirst
java">// 目标:用LinkedList做一个队列对象
LinkedList<String> queue = new LinkedList<>();
// linkedlist独有功能,用list多态引用可能会使用不了
// 入队:addLast()从队尾入队
queue.addLast("张三");// 出队:removeFirst()从队首出队
String name = queue.removeFirst();
  • 设计:后进先出,先进后出 >>> 头进头出
    • 进栈:push
    • 出栈:pop
java">// 做一个栈
LinkedList<String> stack = new LinkedList<>();
// 入栈:addFirst()从队首入栈  push()
stack.addFirst("张三");
stack.push("李四");// 出栈:removeFirst()从队首出栈  pop()
String name2 = stack.removeFirst();
System.out.println(name2);
String name3 = stack.pop();
System.out.println(name3);

7. Collection-Set系列集合:无序(添加顺序和获取顺序不一致)、不重复、无索引

  • HashSet:无序、不重复、无索引
  • LinkedHashSet有序(哈希表)、不重复、无索引
  • TreeSet排序(红黑树)、不重复、无索引

其功能就是Collection的功能继承过来的,因为没有索引,所以也没有新增的功能。

java">// HashSet无序不重复、无索引
Set<String> set = new HashSet<>();
set.add("java");
set.add("java");
set.add("鸿蒙");
set.add("python");
set.add("新媒体");
System.out.println(set);    // [python, java, 鸿蒙, 新媒体]// LinkedHashSet有序不重复、有索引
Set<String> set1 = new LinkedHashSet<>();
set1.add("java");
set1.add("java");
set1.add("鸿蒙");
set1.add("python");
set1.add("新媒体");
System.out.println(set1);   // [java, 鸿蒙, python, 新媒体]// 2、创建一个TreeSet集合:排序(默认要大小升序排序)、不重复、无索引
Set<Double> set2 = new TreeSet<>();
set2.add(3.14);
set2.add(3.14);
set2.add(5.6);
set2.add(1.2);
System.out.println(set2);   // [1.2, 3.14, 5.6]
7.1 HashSet集合的底层原理

课程链接

1)哈希值
  • 一个int类型的随机值java中每个对象都有一个哈希值
  • Java中的所有对象,都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值
    • public int hashCode()
2)对象哈希值的特点
  • 同一个对象多次调用 hashCode()方法返回的哈希值是相同的
  • 不同的对象,他们的哈希值大概率不相等,但也有可能会相等(哈希碰撞)
    • int 范围 (-21亿多~21亿多) vs 创建了 50亿个对象 >>> 就会有重复的哈希值
3)基于哈希表存储数据 >>> 无序、不重复、无索引

哈希表

存储方式变化过程:数组+链表 >>> 数组+链表+红黑树

在这里插入图片描述
在这里插入图片描述

默认加载因子
  • 数据太多时,哈希表中的链表会很长,而链表查询效率很低(需要从头开始查找),所以在达到 加载因子*总长度 个元素时,对哈希表进行扩容
4)红黑树

关于集中排序树的具体含义

当数据已经排好序时,使用链表存储时的二叉查找树就相当于一个单链表

平衡二叉树(左右子树高度差不超过1)

红黑树(可以自平衡的二叉树)

  • 增删改查效率高
5)为什么性能好

查/存/改:底层基于数组,拿到 hash 值后就能通过映射关系算出元素存储的位置

删:找到位置后,直接抹除即可,不用进行数据迁移等操作

7.2 ⭐HashSet集合元素的去重操作 -> 自定义对象

需求:

  • 创建一个存储学生对象的集合,存储多个学生对象

要求:

  • 多个学生对象的成员变量值相同时,我们就认为是同一个对象,要求只保留一个

分析:

① 定义学生类、创建HashSet集合对象、创建学生对象

  • 学生类
java">public class Student {private String name;private int age;private int score;Student() {}Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}'+ '\n';}
}
  • 创建HashSet集合对象,并通过Collections工具类批量添加学生数据
java">Student s1 = new Student("小明", 14, 90);
// ....Set<Student> students = new HashSet<>();// 使用Collections集合工具类批量添加数据
Collections.addAll(students, s1, s2, s3, s4, s5);
System.out.println(students);

在这里插入图片描述

②在学生类中重写两个方法 : hashCode()和equals(),自动生成即可

在这里插入图片描述

③ 遍历集合(增强for)

java">for (Student student : students) {System.out.println(student);
}

在这里插入图片描述

思考🤔🤔🤔
  • 如果在类中使用了 @Data等构造器,会默认重写hashCode()equals()方法的

  • 为什么这些对象在Set集合中没有去重,需要重写方法 ?

    • 创建多个对象时,这几个对象的hash值是不同的,Set不会对其进行去重

    • 要使Set集合认为2个内容一样的对象是重复的,必须重写对象的hashCode()equals()方法

7.3 LinkedHashSet集合的底层原理
  • 有序、不重复、无索引

基于哈希表(数组、链表、红黑树)实现,基于LinkedHashMap编写的

在这里插入图片描述

有序 → 每个元素都额外的多了一个双链表的机制记录它前后元素的位置

在这里插入图片描述在这里插入图片描述

7.4 TreeSet集合的原理

底层基于红黑树实现的排序

  • 对于数值类型:从小到大
java">Set<Double> ts = new TreeSet<>();
Collections.addAll(ts, 3.14, 5.6, 1.2, 3.14);
System.out.println(ts);     // [1.2, 3.14, 5.6]
  • 对于字符串类型:首字符的顺序
java">Set<String> ts2 = new TreeSet<>();
Collections.addAll(ts2, "java", "c++", "python", "java");
System.out.println(ts2);    // [c++, java, python]
  • 自定义类型:默认是无法排序的,不知道大小规则

    • 对象类实现Comparable比较接口重写CompareTo方法,指定大小比较规则
    java">public class Student implements Comparable<Student>{private String name;private int age;private int score;@Override // 重写compareTo方法 :按照年龄升序排序public int compareTo(Student o) {return this.age - o.age;}    
    }
    
    java">Set<Student> ts3 = new TreeSet<>();Collections.addAll(ts3, new Student("小明", 18, 100),new Student("小红", 22, 99),new Student("小刚", 20, 98),new Student("小明", 18, 100));
    System.out.println(ts3);
    
    • public TreeSet 集合自带比较器Comparator对象,指定比较规则
    java">Set<Student> ts3 = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();}
    });// 简化:Set<Student> ts3 = new TreeSet<>(Comparator.comparingInt(Student::getAge));
    

在这里插入图片描述

7.5 什么时候用什么集合呢?

在这里插入图片描述

8. Map集合(键值对集合)

{ key1 = value1 , key2 = value2....}Map<K,V>

⚠️键不重复,值可重复:一个键对应一个值

场景:

  • 需要存储一一对应的数据时
8.1 Map集合分类

在这里插入图片描述

java">// HashMap无序不重复、无索引
Map<String,Integer> map =  new HashMap<>();
map.put("嫦娥",29);
map.put("紫霞",31);
map.put("太白金星",33);
map.put("太白金星",33);
System.out.println(map);    // {嫦娥=29, 太白金星=33, 紫霞=31}// LinedHashMap有序不重复、无索引
Map<String,Integer> map2 =  new LinkedHashMap<>();
// Collections时Collection的工具,不是Map的
map2.put("嫦娥",29);
map2.put("紫霞",31);
map2.put("太白金星",33);
map2.put("太白金星",33);
System.out.println(map2);   // {嫦娥=29, 紫霞=31, 太白金星=33}// TreeMap:按照键可排序,不重复,无索引
Map<String,Integer> map3 =  new TreeMap<>();
map3.put("嫦娥",29);
map3.put("紫霞",31);
map3.put("太白金星",33);
System.out.println(map3);   // {太白金星=33, 嫦娥=29, 紫霞=31}
8.2 Map集合的常用方法

Map是双列集合的祖宗,它的功能是全部双列集合(HashMap,LinkedHashMap,TreeMap)都可以继承的

java">Map<String, Integer> map = new HashMap<>();
map.put("嫦娥",29);
map.put("紫霞",31);
map.put("太白金星",33);
map.put("太白金星",33);
map.put(null,null);
System.out.println(map);    //{null=null, 嫦娥=29, 太白金星=33, 紫霞=31}// get(key):根据键获取值
System.out.println(map.get("嫦娥"));  // 29
// getOrDefault(key, defaultValue):根据键获取值,如果找不到就返回默认值
System.out.println(map.getOrDefault("白骨精", 0)); // 0
// containsKey(key):判断集合中是否有这个键
System.out.println(map.containsKey("嫦娥"));  // true
// containsValue(value):判断集合中是否有这个值
System.out.println(map.containsValue(33));  // true
// remove(key):根据键删除键值对
map.remove("嫦娥");
System.out.println(map);    // {null=null, 太白金星=33, 紫霞=31}
// size():获取集合长度
System.out.println(map.size()); // 3
// keySet():获取所有的键
for (String key : map.keySet()) {System.out.println(key);    // null, 太白金星, 紫霞
}
// values():获取所有的值
Collection<Integer> values = map.values();
System.out.println(values); // [null, 33, 31]
// clear():清空集合
map.clear();
System.out.println(map);    // {}
// isEmpty():判断集合是否为空
System.out.println(map.isEmpty());  // true
8.3 Map集合的遍历方式
1)键找值

keySet() 方法获取全部键 >>> get() 方法通过遍历键找值

  • 提起Map集合的全部键到一个Set集合中
  • 遍历Set集合,得到每一个键
    • 根据键去找值
java">Set<String> keys = map.keySet();	//获取全部键
for (String key : keys) {System.out.println(key + ":" + map.get(key));
}
2)键值对

把 “ 键值对 ” 看成一个整体进行遍历

💡Map提供的entrySet() 方法 >>> 将键值对转为Entry对象,将Map转为Set集合

java">// 将Map集合转换为Set集合,Set集合中存储的元素是Map.Entry类型
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {System.out.println(entry.getKey() + ":" + entry.getValue());
}
3)Lambda表达式

JDK 1.8 后的新技术

java">map.forEach((key, value) -> {System.out.println(key + ":" + value);
});

在这里插入图片描述

源码解析:内部通过将其转为entry对象后遍历,再转为键值对传给重写的accept() 方法

8.4 Map集合的实现类
1)HashMap集合的底层原理

7.1的Set集合的底层是基于Map实现的,只是Set集合中的元素只要键数据,不要值数据

2)LinkedHashMap的底层原理

LinkedHashSet底层原理基于LinkedHashMap在这里插入图片描述

3)TreeMap的底层原理,同TreeSet集合
  • 特点:不重复、无索引、可排序(按照键的大小默认升序排序,只能对键排序)
  • 原理:TreeMapTreeSet集合的底层原理是一样的,都是基于红黑树实现的排序

排序方式

  • 让类实现Comparable接口,重写比较规则,同TreeSet
  • TreeMap集合有一个有参数构造器,支持构建Comparator比较器对象,以便用来指定比较规则
java">// 使用TreeMap的构造器传入比较器对象,并简化
// 按照分数升序
Map<Student, String> studentMap = new TreeMap<>((o1, o2) -> o1.getScore() - o2.getScore());
//  Map<Student, String> studentMap = new TreeMap<>(Comparator.comparingInt(Student::getScore));studentMap.put(new Student("小明", 18, 100), "北京");
studentMap.put(new Student("小红", 19, 94), "上海");
studentMap.put(new Student("小亮", 22, 98), "广州");
studentMap.put(new Student("小丽", 21, 95), "深圳");
studentMap.put(new Student("小华", 22, 96), "武汉");
System.out.println(studentMap);

8.5 Map集合的案例-统计投票信息

需求

  • 某个班级80名学生,现在需要组织秋游活动,班长提供了四个景点依次是(A、B、C、D),每个学生只能选择一个景点,请统计出最终哪个景点想去的人数最多

分析:

  • 出现了一 一对应的数据 >>> 键值对存储
  • 将80个学生选择的数据拿到程序中去
  • 准备一个Map集合用于存储统计的结果
  • 遍历80个学生选择的景点,每遍历一个景点,就看Map集合中是否存在该景点,不存在存入"景点 = 1",存在则其对应值 + 1
java">// 四个景点
String[] names = {"A", "B", "C", "D"};
// 80名学生的投票数据:用List集合存储
List<String> votes = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 80; i++) {int index = r.nextInt(names.length);    // 随机获取索引 0 1 2 3votes.add(names[index]);
}// 整理投票结果,用Map集合存储统计结果
Map<String,Integer> map = new HashMap<>();
for (String vote : votes) {if(map.containsKey(vote)){  // 如果Map集合中包含该景点,则将投票人数加1map.put(vote, map.get(vote) + 1);}else{  // 如果Map集合中不包含该景点,则将投票人数设置为1map.put(vote, 1);}
}
  • 统计投票简化代码
java">for (String vote : votes) {
//  map.put(vote, map.getOrDefault(vote, 0) + 1);map.put(vote, map.containsKey(vote) ? map.get(vote) + 1 : 1);
}

在这里插入图片描述


Stream流

👍用于操作集合或者数组的数据

💡Stream流大量的结合了Lambda的语法风格来编程,功能强大,性能高效,代码简洁,可读性好

  • 处理数据的步骤

1)准备数据源

java">List<String> list = new ArrayList<>();
Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");

2)获取数据源的Stream流

3)调用流水线的各种方法,对数据进行处理

4)获取处理的结果

java">newList = list.stream().filter(name -> name.startsWith("张")) // 以“张”开头的 -> 姓张的.filter(name -> name.length() == 3)		// 名字是三个字的.collect(Collectors.toList());		// 收集方法:将结果流转为list集合
  • 对比传统方式
java">List<String> newList = new ArrayList<>();
for (String name : list) {if (name.startsWith("张") && name.length() == 3) {newList.add(name);}
}
System.out.println(newList);

在这里插入图片描述

1. 获取Stream流

  • 获取集合的Stream流

    • Collection提供了获取当前集合对象的Stream流的方法
    java">Collection<String> list = new ArrayList<>();
    Stream<String> s1 = list.stream();
    
  • 获取数组的Stream流

    • Arrays类提供了获取当前数组的Stream流的方法
    java">String[] arr = {"林青霞", "张曼玉", "王祖蓝"};
    Stream<String> s5 = Arrays.stream(arr);
    System.out.println(s5.count());
    
    • Stream类提供了获取当前接收数据的Stream流的方法
    java">Stream<String> s6 = Stream.of(arr);
    Stream<String> s7 = Stream.of("林青霞", "张曼玉", "王祖蓝");
    
  • 获取Map集合的Stream流

    • 获取键流
    java">Stream<String> s2 = map.keySet().stream();
    
    • 获取值流
    java"> Stream<Integer> s3 = map.values().stream();
    
    • 获取键值流:将Map集合转为Set集合,再获取Stream流
    java">Stream<Map.Entry<String, Integer>> s4 = map.entrySet().stream();
    

2. 常用中间方法

🤔作为中间方法,调完后会返回新流

在这里插入图片描述

java">ArrayList<Double> list = new ArrayList<>();
Collections.addAll(list, 1.2, 3.4, 5.6, 7.8, 9.0);
System.out.println(list);
// 过滤方法 filter()
list.stream().filter(num -> num > 5).forEach(System.out::println);
System.out.println("--------------------------------------------------");
// 排序方法 sorted() 默认升序  降序需重写Comparator接口的compare方法
// 从大到小 :
Stream<Double> sorted1 =list.stream().sorted((num1, num2) -> num2.compareTo(num1));
sorted1.forEach(System.out::println);
// 从小到大
Stream<Double> sorted2 =list.stream().sorted(Double::compareTo);  // 进一步简化了的(num1, num2) -> num1.compareTo(num2) 
sorted2.forEach(System.out::println);
System.out.println("--------------------------------------------------");
// 获取前几个元素 limit()
list.stream().limit(3).forEach(System.out::println);
// 跳过前几个元素 skip()
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------------------------------------------------");
// 对元素进行加工,并返回对应的新流 map()
list.stream().map(num -> num * 2).forEach(System.out::println);
System.out.println("--------------------------------------------------");
// 合并两个流 concat()
Stream<Double> stream1 = list.stream();
Stream<Double> stream2 = Stream.of(1.2, 3.4, 5.6, 7.8, 9.0);
Stream<Double> stream3 = Stream.concat(stream1, stream2);
System.out.println(stream3.count());

3. 常用终结方法

💡终结:使用后不会返回新的流

在这里插入图片描述

3.1 常用终结方法

在获取最大值时,还需要通过get获取Optional对象中的元素

java">// 1、统计流中元素的个数:count()
ArrayList<Student> students = new ArrayList<>();
Collections.addAll(students, new Student("张三", 18, 100),new Student("李四", 22, 79),new Student("王五", 20, 80));
System.out.println(students.stream().count());  // 3
System.out.println("===========================================================");
// 2、获取此流运算后的最大值元素:max()
Optional<Student> max = students.stream().max((s1, s2) -> s1.getScore() - s2.getScore());
Student student = max.get();
System.out.println(student);    // Student{name='张三', age=18, score=100}
3.2 收集Stream流:

把Stream流操作后的结果转回到集合或者数组中

⚠️流只能收集一次

在这里插入图片描述

  • collect(Collector collector) : 把流处理后的结果收集到一个指定的集合中去
    • Collectors 又分为 toList()toSet()toMap()
java">ArrayList<String> names = new ArrayList<>();
Collections.addAll(names, "张三", "李四", "王五", "赵六", "张无忌");
Stream<String> s1 = names.stream().filter(name -> name.startsWith("张"));
// 收集Stream流到Set集合中
Set<String> set = s1.collect(Collectors.toSet());
System.out.println(set);// 收集Stream流到数组中
Stream<String> s2 = names.stream().filter(name -> name.startsWith("张"));
Object[] arr = s2.toArray();	// 注意返回类型为Object
System.out.println("数组:" + Arrays.toString(arr));
  • toArray() 方法的返回类型是Object[] , 因为 Stream 默认不知道具体的泛型类型,因此只能返回 Object[]
  • Arrays.toString将数组的内容转换为字符串形式,便于打印和调试
java">// 收集到Map集合中
ArrayList<Student> students = new ArrayList<>();
Collections.addAll(students,new Student("张三", 18, 100),new Student("李四", 22, 99),new Student("王五", 20, 98),new Student("赵六", 19, 97),new Student("张无忌", 22, 96)
);// 简化:Map<String,Integer> map = students.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
Map<String, Integer> map = students.stream().collect(Collectors.toMap(new Function<Student, String>() {@Overridepublic String apply(Student student) {return student.getName();}}, new Function<Student, Integer>() {@Overridepublic Integer apply(Student student) {return student.getAge();}}
));System.out.println(map);

在这里插入图片描述


http://www.ppmy.cn/server/175933.html

相关文章

TP钱包密码忘记了怎么办?(TokenPocket)——技术角度解决方案分析

​ TP钱包&#xff08;TokenPocket&#xff09; 作为一款多链支持的数字货币钱包&#xff0c;广泛用于存储和管理各种加密资产。尽管它在操作上相对简便&#xff0c;但在用户未能妥善保存重要信息&#xff08;如密码或助记词&#xff09;的情况下&#xff0c;忘记密码会带来不小…

DICOM医学影像数据加密技术应用的重要性及其实现方法详解

DICOM医学影像数据加密技术应用的重要性及其实现方法详解 引言 随着医疗信息化的快速发展,DICOM(Digital Imaging and Communications in Medicine,数字医学影像与通信)标准已成为全球广泛应用的医学影像数据传输和存储规范。DICOM不仅规范了医学影像的格式,还涵盖了数据…

Flutter 按钮组件 ElevatedButton 详解

目录 1. 引言 2. ElevatedButton 的基本用法 3. 主要属性 4. 自定义按钮样式 4.1 修改背景颜色和文本颜色 4.2 修改按钮形状和边框 4.3 修改按钮大小 4.4 阴影控制 4.5 水波纹效果 5. 结论 相关推荐 1. 引言 在 Flutter 中&#xff0c;ElevatedButton 是一个常用的…

短视频下载去水印,用什么工具好?

去除视频和图片水印是许多用户的需求&#xff0c;尤其是在分享或保存内容时。以下是6款超好用的工具&#xff0c;帮助你轻松去除水印&#xff0c;享受纯净的视觉体验&#xff1a; 1. 易下载去水印小程序 特点&#xff1a; 操作简单&#xff0c;支持抖音、快手、小红书、哔哩哔哩…

Linux搭建conda虚拟环境流程

文章目录 Requirements搭建虚拟环境方法 1&#xff1a;使用 --prefix 参数删除指定路径的虚拟环境方法 2&#xff1a;手动删除指定路径的虚拟环境 requirements.txt实验室电脑装环境一些问题&#xff1a;numpy包问题&#xff1a;1. **确保环境干净并重新安装 numpy**&#xff0…

pip install和conda install的区别

这里写目录标题 一、什么是 Python 依赖&#xff08;Python Dependencies&#xff09;&#xff1f;1. 依赖的作用2. 如何管理 Python 依赖3. 依赖管理问题4. 依赖锁定总结 二、使用pip安装包venv隔离环境方法 1&#xff1a;使用 venv&#xff08;推荐&#xff09;创建虚拟环境激…

[QT]开发全解析:从概念到实战

文章目录 Qt 框架入门与应用开发指南一、Qt 框架概述1.1 什么是 Qt1.2 Qt 的发展史1.3 Qt 支持的平台1.4 Qt 版本1.5 Qt 的优点1.6 Qt 的应用场景1.7 Qt 的成功案例 二、Qt 的开发工具概述Qt CreatorVisual StudioEclipse 三、认识 Qt Creator3.1 Qt Creator 概览3.2 使用 Qt C…

五子棋小游戏-简单开发版

一、需求分析 开发一个基于 Pygame 库的五子棋小游戏&#xff0c;允许两名玩家在棋盘上轮流落子&#xff0c;当有一方达成五子连珠时游戏结束&#xff0c;显示获胜信息&#xff0c;并提供退出游戏和重新开始游戏的操作选项。 1.棋盘显示 &#xff1a; 显示一个 15x15 的五子棋…