Java Stream流操作

编程入门 行业动态 更新时间:2024-10-26 06:27:24

Java Stream流<a href=https://www.elefans.com/category/jswz/34/1770947.html style=操作"/>

Java Stream流操作

文章目录

  • 前言
  • 一、Java Stream 简介
  • 二、流与集合的区别
    • 2.1 数据存储方式
    • 2.2 处理方式
  • 三、流的组成
    • 3.1 数据源(Source):
    • 3.2 中间操作(Intermediate Operations):
    • 3.3 终端操作(Terminal Operations):
    • 3.4并行与顺序处理:
  • 四、流的操作分类
    • 4.1 中间操作(Intermediate Operations):
    • 4.2 终端操作(Terminal Operations):
  • 五、流的使用
    • 5.1 中间操作(无状态):
    • 5.2 中间操作(有状态):
    • 5.3 终端操作(短路):
    • 5.4 终端操作(非短路):
  • 六、流的构建
    • 6.1 通过集合(Collection)创建流
    • 6.2 通过数组创建流
    • 6.3 通过值创建流
    • 6.4 通过函数生成流
    • 6.5 通过文件生成流
    • 6.6 通过其他流生成流
  • 七、流实战
    • 7.1 实体
    • 7.2 创建并行流(多线程处理)
    • 7.3 遍历/匹配(foreach/find/match)
    • 7.4 filter
    • 7.5 聚合(max/min/count)
    • 7.6 map/flatMap 映射
    • 7.7 reduce 归约
    • 7.8 collect(toList/toSet/toMap)
    • 7.9 统计(count/averaging)
    • 7.10 分组(partitioningBy/groupingBy)
    • 7.11 接合(joining)
    • 7.12 排序(sorted)
    • 7.13 合并、去重、限制、跳过
  • 八、总结


前言

Java Stream 是 Java 8 中引入的一个新特性,它的出现主要是为了解决传统操作方式的一些问题,并提供更为简洁、灵活和高效的操作方式,可以大大提高代码的开发效率和质量。因此,在使用 Java 编程时,推荐使用 Stream 流来进行数据处理和操作。


一、Java Stream 简介

Java Stream 是一种处理集合数据的新方法,它提供了一种简单、高效、并行化的方式来处理集合数据。Java Stream 可以用于任何类型的集合数据,包括 List、Set、Map 等。

优点如下:

  1. 更为简洁和灵活:使用 Stream 流可以大大简化代码逻辑,避免繁琐的循环和条件判断,使代码更加简洁、易读和易维护。同时,Stream 流提供了丰富的中间操作和终止操作,可以根据具体的需求选择不同的操作方式,实现更为灵活和多样化的操作。

  2. 更高效的处理方式:Stream 流采用的是惰性求值的方式,即只有在终止操作时才会进行计算,避免了不必要的计算和内存占用。同时,Stream 流还可以利用多核处理器进行并行计算,提高处理效率和性能。

  3. 更为安全和可靠:Stream 流提供了类型检查和空指针检查等机制,避免了一些常见的编程错误和异常情况,提高了代码的安全性和可靠性。

  4. 更好的代码可读性:Stream 流提供了丰富的操作方法和语法糖,可以使代码更加简洁、易读和易懂,提高了代码的可读性和可维护性。


二、流与集合的区别

流(Stream)和集合(Collection)是 Java 中两种不同的概念,它们虽然都可以用来存储一组数据,但在使用方式、处理方式和特性上存在很大的区别。

2.1 数据存储方式

  1. 集合是一种数据结构,它可以存储一组对象或基本类型的值。常见的集合包括 List、Set、Map 等,它们都有自己的特点和适用场景。
  2. 流则是一种数据处理方式,它并不直接存储数据,而是对数据进行操作和处理。流可以从集合、数组、文件等数据源中获取数据,并将数据流式地传输到下一个操作中。

2.2 处理方式

  1. 集合提供了一系列的方法来操作其中的元素,比如添加、删除、遍历、查找等。集合中的元素是立即求值的,也就是说,当你调用集合的方法时,会立即执行相应的操作。

  2. 流则是惰性求值的,它不会立即执行操作,而是等到需要结果时才会执行。流的操作可以分为两类:中间操作和终端操作。中间操作返回的仍然是流,可以进行链式调用;终端操作则返回一个结果或副作用,触发流的处理。

  3. 特性

集合具有以下特性:

  • 可以重复存储相同的元素;
  • 可以按照插入顺序或自定义顺序进行排序;
  • 可以通过索引访问元素;
  • 可以通过迭代器遍历元素。

流具有以下特性:

  • 不存储数据,不会改变数据源的内容;
  • 可以进行并行处理,提高处理效率;
  • 可以进行多次操作,每次操作都返回一个新的流;
  • 可以对无限流进行操作,比如生成一系列随机数。

三、流的组成

Java Stream 是由一系列操作组成的,这些操作可以被串联起来形成一个流水线,对数据进行处理和转换。Stream 流的组成主要包括以下几个部分:

3.1 数据源(Source):

数据源是 Stream 流的起点,可以是集合、数组、I/O 通道、生成器等。Stream 可以从数据源中获取元素并传递给后续的操作。

3.2 中间操作(Intermediate Operations):

中间操作是对数据进行处理和转换的操作,它们可以接收一个流作为输入,返回一个新的流作为输出。中间操作可以有零个或多个,常见的中间操作包括过滤、映射、排序、去重等。

3.3 终端操作(Terminal Operations):

终端操作是对流进行最终操作的操作,它们会触发流的处理并产生一个结果或副作用。终端操作可以有一个或多个,常见的终端操作包括收集到集合、聚合计算、迭代遍历、条件匹配等。

3.4并行与顺序处理:

Stream 流可以进行并行处理,即利用多线程同时处理数据,提高处理效率。通过调用 parallel() 方法可以将流切换为并行流,而调用 sequential() 方法可以将并行流切换为顺序流。

Stream 流的组成使得我们可以通过链式调用的方式来对数据进行一系列的处理操作,使代码更加简洁、易读、易维护。同时,Stream 流的惰性求值特性也能够避免不必要的计算,提高了处理效率。需要注意的是,Stream 流是一次性使用的,一旦对流进行了终端操作,就无法再对其进行其他操作。如果需要多次使用流,可以通过创建新的流来实现。


四、流的操作分类

4.1 中间操作(Intermediate Operations):

中间操作是指在流上执行的操作,它们不会产生最终结果,而是返回一个新的流,用于进一步的操作。中间操作可以分为两种类型:

  1. 无状态操作(Stateless Operations):
    无状态操作是指不依赖于流中前面的元素,每个元素的处理都是独立的。常见的无状态操作有:map()、filter()、flatMap() 等。
  2. 有状态操作(Stateful Operations):
    有状态操作是指需要依赖于流中前面的元素进行计算的操作,这些操作需要维护状态,并且可能会影响后面的操作。常见的有状态操作有:distinct()、sorted()、peek() 等。

4.2 终端操作(Terminal Operations):

终端操作是指流的最终操作,在执行终端操作后,流将被消耗,不能再进行其他操作。常见的终端操作有:forEach()、count()、collect()、reduce() 等。

  1. 非短路操作(Non-Short-Circuiting Operations):
    非短路操作是指流中的所有元素都会被处理的操作,即无论流中有多少元素,都会对其进行操作,直到处理完所有元素。常见的非短路操作有:forEach()、collect()、reduce() 等。
  2. 短路操作(Short-Circuiting Operations):
    短路操作是指在处理流时,只处理部分元素,而不是全部元素,可以提高处理效率。常见的短路操作有:findFirst()、findAny()、limit()、skip() 等。

五、流的使用

流操作可以分为中间操作和终端操作两种类型。中间操作是指对流进行处理并返回一个新的流,而终端操作是指对流进行最终的处理并产生一个结果。

5.1 中间操作(无状态):

  • filter:根据指定的条件过滤流中的元素,只保留满足条件的元素。
  • map:将流中的每个元素通过指定的函数进行映射转换,生成一个新的流。
  • flatMap:将流中的每个元素通过指定的函数进行映射转换,并将映射结果扁平化为一个新的流。
  • peek:对流中的每个元素执行指定的操作,可以用于调试或观察流中的元素。

5.2 中间操作(有状态):

  • distinct:去除流中重复的元素,使用元素的 equals 方法进行比较。
  • skip:跳过指定数量的元素,返回剩下的元素组成的新流。
  • limit:限制流中元素的数量,截取前面指定数量的元素组成新流。
  • sorted:对流中的元素进行排序,可以使用自然顺序或指定的比较器。

5.3 终端操作(短路):

  • allMatch:判断流中的所有元素是否都满足指定条件,如果有一个不满足则返回 false。
  • anyMatch:判断流中是否存在任意一个元素满足指定条件,如果有则返回 true。
  • noneMatch:判断流中是否不存在任何一个元素满足指定条件,如果没有则返回 true。
  • findFirst:返回流中的第一个元素。
  • findAny:返回流中的任意一个元素。

5.4 终端操作(非短路):

  • forEach:对流中的每个元素执行指定的操作。
  • reduce:将流中的元素通过指定的操作进行归约计算,得到一个结果。
  • max:返回流中的最大元素,根据自然顺序或指定的比较器进行比较。
  • min:返回流中的最小元素,根据自然顺序或指定的比较器进行比较。
  • collect:将流中的元素收集到一个集合或其他数据结构中。
  • count:返回流中的元素数量。

六、流的构建

6.1 通过集合(Collection)创建流

List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> stream = list.stream();

6.2 通过数组创建流

String[] array = {"apple", "banana", "orange"};
Stream<String> stream = Arrays.stream(array);

6.3 通过值创建流

Stream<String> stream = Stream.of("apple", "banana", "orange");

6.4 通过函数生成流

Stream<Integer> stream = Stream.generate(() -> 1); // 生成一个无限流,每个元素都是 1
Stream<Integer> stream = Stream.iterate(0, n -> n + 2); // 生成一个无限流,每个元素递增 2

6.5 通过文件生成流

try {Stream<String> stream = Files.lines(Paths.get("file.txt"));
} catch (IOException e) {// 处理异常
}

6.6 通过其他流生成流

Stream<String> originalStream = Stream.of("apple", "banana", "orange");
Stream<String> newStream = originalStream.filter(s -> s.startsWith("a")); // 过滤以字母"a"开头的元素
Stream stream = Stream.generate(Math::random);
stream.limit(100).forEach(System.out::println);

七、流实战

7.1 实体

public class Person {private String name;  // 姓名private Integer salary; // 薪资private int age; // 年龄private String sex; //性别private String area;  // 地区public Person() {}public Person(String name, Integer salary, int age, String sex, String area) {this.name = name;this.salary = salary;this.age = age;this.sex = sex;this.area = area;}public Person(String name, Integer salary, String sex, String area) {this.name = name;this.salary = salary;this.sex = sex;this.area = area;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getSalary() {return salary;}public void setSalary(int salary) {this.salary = salary;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getArea() {return area;}public void setArea(String area) {this.area = area;}@Overridepublic String toString() {final StringBuffer sb = new StringBuffer("Person{");sb.append("name='").append(name).append('\'');sb.append(", salary=").append(salary);sb.append(", age=").append(age);sb.append(", sex='").append(sex).append('\'');sb.append(", area='").append(area).append('\'');sb.append('}');return sb.toString();}
}
public class User {String name;Integer sex;Integer age;User user;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getSex() {return sex;}public void setSex(Integer sex) {this.sex = sex;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public User getUser() {return user;}public void setUser(User user) {this.user = user;}public User(String name, Integer sex, Integer age) {this.name = name;this.sex = sex;this.age = age;}public User(String name, Integer sex, Integer age, User user) {this.name = name;this.sex = sex;this.age = age;this.user = user;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;User user1 = (User) o;return Objects.equals(name, user1.name) && Objects.equals(sex, user1.sex) && Objects.equals(age, user1.age) && Objects.equals(user, user1.user);}@Overridepublic int hashCode() {return Objects.hash(name, sex, age, user);}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", sex=" + sex +", age=" + age +'}';}
}

7.2 创建并行流(多线程处理)

@Testpublic void test02() {List<Integer> list = Arrays.asList(3, 8, 2, -3, 10, 0, 10);// Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。Optional<Integer> findFirst = list.stream().parallel().filter(x -> x > 6).findFirst();findFirst.ifPresent(System.out::println);System.out.println("findFirst.isPresent() = " + findFirst.isPresent());}

7.3 遍历/匹配(foreach/find/match)

@Test
public void test03() {List<Integer> list = Arrays.asList(7, 9, 3, 8, 12, 2, 1);list.stream().filter(x -> x > 6).forEach(System.out::println);// 匹配第一个Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();// 是否包含符合特定条件的元素boolean anyMatch = list.stream().anyMatch(x -> x < 1);System.out.println("匹配第一个值:" + findFirst.orElse(null)); // 7System.out.println("匹配任意一个值:" + findAny.orElse(null)); // 8System.out.println("是否存在小于1的值:" + anyMatch); // false
}

7.4 filter

@Test
public void test04() {List<Person> personList = new ArrayList<>();personList.add(new Person("Tom", 8900, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", 7800, 21, "female", "Washington"));personList.add(new Person("Anni", 8200, 24, "female", "New York"));personList.add(new Person("Owen", 9500, 25, "male", "New York"));personList.add(new Person("Alisa", 7900, 26, "female", "New York"));List<String> fiterList = personList.stream().filter(x -> "male".equals(x.getSex()) && x.getSalary() > 8000).map(Person::getName).collect(Collectors.toList());System.out.print("高于8000的男员工姓名:" + fiterList);
}

7.5 聚合(max/min/count)

@Test
public void test05() {List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");Optional<String> max = list.stream().max(Comparatorparing(String::length));System.out.println("最长的字符串:" + max.get());List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 8900, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", 7800, 21, "female", "Washington"));personList.add(new Person("Anni", 8200, 24, "female", "New York"));personList.add(new Person("Owen", 9500, 25, "male", "New York"));personList.add(new Person("Alisa", 7900, 26, "female", "New York"));System.out.println(personList.stream().max(ComparatorparingInt(Person::getSalary)).get());System.out.println(personList.stream().min(Comparatorparing(Person::getSalary)).get());List<Integer> integers = Arrays.asList(7, 6, 9, 4, 11, 6);System.out.println(integers.stream().min(Integer::compareTo).get());System.out.println(integers.stream().max(ComparatorparingInt(param -> param)).get());
}

7.6 map/flatMap 映射

@Test
public void test06() {String[] strArr = {"abcd", "bcdd", "defde", "fTr"};List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());System.out.println("每个元素大写:" + strList);// 每个元素大写:[ABCD, BCDD, DEFDE, FTR]System.out.println("每个元素+3:" + intListNew);// 每个元素+3:[4, 6, 8, 10, 12, 14]List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 8900, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", 7800, 21, "female", "Washington"));personList.add(new Person("Anni", 8200, 24, "female", "New York"));personList.add(new Person("Owen", 9500, 25, "male", "New York"));personList.add(new Person("Alisa", 7900, 26, "female", "New York"));// 不改变原来员工集合的方式List<Person> personListNew = personList.stream().map(person -> {Person newPerson = new Person();BeanUtils.copyProperties(person, newPerson);newPerson.setSalary(person.getSalary() + 1000);return newPerson;}).collect(Collectors.toList());System.out.println("一次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary()); // 一次改动前:Tom-->8900System.out.println("一次改动后:" + personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());// 一次改动后:Tom-->9900List<Person> personListNew2 = personList.stream().map(person -> {person.setSalary(person.getSalary() + 10000);return person;}).collect(Collectors.toList());System.out.println("二次改动前:" + personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());// 二次改动前:Tom-->9900System.out.println("二次改动后:" + personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());// 二次改动后:Tom-->9900List<String> list = Arrays.asList("m/k/l/a", "1/3/5/7");List<String> listNew = list.stream().flatMap(s -> {// 将每个元素转换成一个streamString[] split = s.split("/");Stream<String> s2 = Arrays.stream(split);return s2;}).collect(Collectors.toList());System.out.println("处理前的集合:" + list);// 处理前的集合:[m/k/l/a, 1/3/5/7]System.out.println("处理后的集合:" + listNew);// 处理后的集合:[m, k, l, a, 1, 3, 5, 7]
}
// 并行流写法Map<Integer, List<User>> collect3 = list.parallelStream().filter((User user) -> user.getAge() != null && Integer.valueOf(10)pareTo(user.getAge()) < 0).collect(Collectors.groupingBy(User::getAge));

7.7 reduce 归约

@Test
public void test07() {List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 8900, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", null, 21, "female", "Washington"));personList.add(new Person("Anni", 8200, 24, "female", "New York"));personList.add(new Person("Owen", 9500, 25, "male", "New York"));personList.add(new Person("Alisa", 7900, 26, "female", "New York"));// 求工资之和Optional<Integer> reduce = personList.stream().map(Person::getSalary).filter(Objects::nonNull).reduce(Integer::sum);Integer sumSalary = reduce.orElse(0);Integer sumSalary2 = personList.stream().filter(person -> person.getSalary() != null).reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);Integer sumSalary3 = personList.stream().filter(person -> person.getSalary() != null).reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);System.out.println("工资之和:" + sumSalary + "," + sumSalary2 + "," + sumSalary3); // 工资之和:41500,41500,41500// 最高工资Integer maxSalary = personList.stream().filter(person -> person.getSalary() != null).reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), Integer::max);Integer maxSalary2 = personList.stream().filter(person -> person.getSalary() != null).reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), (max1, max2) -> max1 > max2 ? max1 : max2);System.out.println("工资最大值:" + maxSalary + "," + maxSalary2); // 工资最大值:9500,9500List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);// 求和方式1Optional<Integer> sum = list.stream().reduce(Integer::sum);// 求和方式2Optional<Integer> sum2 = list.stream().reduce(Integer::sum);// 求和方式3Integer sum3 = list.stream().reduce(0, Integer::sum);// 求乘积Optional<Integer> product = list.stream().reduce((x, y) -> x * y);// 求最大值方式1Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);// 求最大值写法2Integer max2 = list.stream().reduce(1, Integer::max);System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);// list求和:29,29,29System.out.println("list求积:" + product.get());// list求积:2112System.out.println("list求和:" + max.get() + "," + max2);// list求和:11,11
}

7.8 collect(toList/toSet/toMap)

@Test
public void test08() {List<Integer> list = Arrays.asList(1, 6, 3, 4, 6, 7, 9, 6, 20);List<Integer> listNew = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());System.out.println(listNew); // [6, 4, 6, 6, 20]Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());System.out.println(set); // [4, 20, 6]List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", null, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", 7800, 21, "female", "Washington"));personList.add(new Person("Anni", 8200, 24, "female", "New York"));Map<String, Person> collect = personList.stream().filter(p -> p.getSalary() != null && p.getSalary() > 8000).collect(Collectors.toMap(Person::getName, p -> p));Map<String, String> collect2 = personList.stream().filter(p -> p.getSalary() != null && p.getSalary() > 8000).collect(Collectors.toMap(Person::getName, JSONObject::toJSONString));System.out.println(collect); // {Anni=Person{name='Anni', salary=8200, age=24, sex='female', area='New York'}}System.out.println(collect2); // {Anni={"age":24,"area":"New York","name":"Anni","salary":8200,"sex":"female"}}
}

7.9 统计(count/averaging)

/*** 计数:count* 平均值:averagingInt、averagingLong、averagingDouble* 最值:maxBy、minBy* 求和:summingInt、summingLong、summingDouble* 统计以上所有:summarizingInt、summarizingLong、summarizingDouble*/
@Test
public void test09() {List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 3234, 23, "male", "New York"));personList.add(new Person("Jack", 433, 25, "male", "Washington"));personList.add(new Person("Lily", 4334, 21, "female", "Washington"));personList.add(new Person("test", null, 21, "female", "china"));// 数据条数long count = personList.stream().filter(p -> p.getSalary() != null).count();long count2 = personList.stream().filter(p -> p.getSalary() != null).count();// 平均工资Double average = personList.stream().filter(p -> p.getSalary() != null).collect(Collectors.averagingDouble(Person::getSalary));// 求工资之和int sum = personList.stream().filter(p -> p.getSalary() != null).mapToInt(Person::getSalary).sum();int sum2 = personList.stream().filter(p -> p.getSalary() != null).mapToInt(Person::getSalary).sum();// 工资最大值Optional<Integer> max = personList.stream().map(Person::getSalary).filter(Objects::nonNull).max(Integer::compare);Optional<Integer> max2 = personList.stream().map(Person::getSalary).filter(Objects::nonNull).max(Integer::compare);// 一次性统计所有信息// DoubleSummaryStatistics{count=3, sum=23700.000000, min=7000.000000, average=7900.000000, max=8900.000000}// 包括条数,总和,平均值,最大值,最小值DoubleSummaryStatistics collect = personList.stream().filter(p -> p.getSalary() != null).collect(Collectors.summarizingDouble(Person::getSalary));System.out.println("员工总数:" + count + "," + count2); // 员工总数:3,3System.out.println("员工平均工资:" + average);// 员工平均工资:2667.0System.out.println("员工工资总和:" + sum + "," + sum2);// 员工工资总和:8001,8001System.out.println("员工工资所有统计:" + collect);// 员工工资所有统计:DoubleSummaryStatistics{count=3, sum=8001.000000, min=433.000000, average=2667.000000, max=4334.000000}System.out.println("员工工资最大值:" + (max.orElseGet(() -> 0)) + "," + (max2.orElseGet(() -> 0)));// 员工工资最大值:4334,4334
}

7.10 分组(partitioningBy/groupingBy)

@Test
public void test10() {List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 8900, "male", "New York"));personList.add(new Person("Jack", 7000, "male", "Washington"));personList.add(new Person("Lily", 7800, "female", "Washington"));personList.add(new Person("Anni", 8200, "female", "New York"));personList.add(new Person("Owen", 9500, "male", "New York"));personList.add(new Person("Alisa", 7900, "female", "New York"));// 分区// 将员工按薪资是否高于8000分组Map<Boolean, List<Person>> collect = personList.stream().collect(Collectors.partitioningBy(p -> p.getSalary() > 8000));List<Person> people = collect.get(false);// people = [Person{name='Jack', salary=7000, age=0, sex='male', area='Washington'}, // Person{name='Lily', salary=7800, age=0, sex='female', area='Washington'}, // Person{name='Alisa', salary=7900, age=0, sex='female', area='New York'}]System.out.println("people = " + people);List<Person> people2 = collect.get(true);// people2 = [Person{name='Tom', salary=8900, age=0, sex='male', area='New York'}, // Person{name='Anni', salary=8200, age=0, sex='female', area='New York'}, // Person{name='Owen', salary=9500, age=0, sex='male', area='New York'}]System.out.println("people2 = " + people2);// 将员工按性别分组Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));// group = {female=[Person{name='Lily', salary=7800, age=0, sex='female', area='Washington'}, // Person{name='Anni', salary=8200, age=0, sex='female', area='New York'}, // Person{name='Alisa', salary=7900, age=0, sex='female', area='New York'}], // male=[Person{name='Tom', salary=8900, age=0, sex='male', area='New York'}, // Person{name='Jack', salary=7000, age=0, sex='male', area='Washington'}, // Person{name='Owen', salary=9500, age=0, sex='male', area='New York'}]}System.out.println("group = " + group);// 将员工先按性别分组,再按地区分组Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));// 员工按性别、地区:{female={New York=[Person{name='Anni', salary=8200, age=0, sex='female', area='New York'}, // Person{name='Alisa', salary=7900, age=0, sex='female', area='New York'}], // Washington=[Person{name='Lily', salary=7800, age=0, sex='female', area='Washington'}]}, // male={New York=[Person{name='Tom', salary=8900, age=0, sex='male', area='New York'}, // Person{name='Owen', salary=9500, age=0, sex='male', area='New York'}], // Washington=[Person{name='Jack', salary=7000, age=0, sex='male', area='Washington'}]}}System.out.println("员工按性别、地区:" + group2);
}

7.11 接合(joining)

@Test
public void test11() {List<Person> personList = new ArrayList<Person>();personList.add(new Person("Tom", 8900, 23, "male", "New York"));personList.add(new Person("Jack", 7000, 25, "male", "Washington"));personList.add(new Person("Lily", 7800, 21, "female", "Washington"));String names = personList.stream().map(Person::getName).collect(Collectors.joining(","));// 所有员工的姓名:Tom,Jack,LilySystem.out.println("所有员工的姓名:" + names);
}

7.12 排序(sorted)

@Test
public void test13() {List<Person> personList = new ArrayList<Person>();personList.add(new Person("Sherry", 9000, 24, "female", "New York"));personList.add(new Person("Tom", 8900, 22, "male", "Washington"));personList.add(new Person("Jack", 9000, 25, "male", "Washington"));personList.add(new Person("Lily", 8800, 26, "male", "New York"));personList.add(new Person("Alisa", 9000, 26, "female", "New York"));// 按工资升序排序(自然排序)List<String> newList = personList.stream().sorted(Comparatorparing(Person::getSalary)).map(Person::getName).collect(Collectors.toList());// 按工资倒序排序List<String> newList2 = personList.stream().sorted(Comparatorparing(Person::getSalary).reversed()).map(Person::getName).collect(Collectors.toList());// 先按工资再按年龄升序排序List<String> newList3 = personList.stream().sorted(Comparatorparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName).collect(Collectors.toList());// 先按工资再按年龄自定义排序(降序)List<String> newList4 = personList.stream().sorted((p1, p2) -> {if (Objects.equals(p1.getSalary(), p2.getSalary())) {return p2.getAge() - p1.getAge();} else {return p2.getSalary() - p1.getSalary();}}).map(Person::getName).collect(Collectors.toList());// 按工资升序排序:[Lily, Tom, Sherry, Jack, Alisa]// 按工资降序排序:[Sherry, Jack, Alisa, Tom, Lily]// 先按工资再按年龄升序排序:[Lily, Tom, Sherry, Jack, Alisa]// 先按工资再按年龄自定义降序排序:[Alisa, Jack, Sherry, Tom, Lily]System.out.println("按工资升序排序:" + newList);System.out.println("按工资降序排序:" + newList2);System.out.println("先按工资再按年龄升序排序:" + newList3);System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
}

7.13 合并、去重、限制、跳过

@Test
public void test15() {String[] arr1 = {"a", "b", "c", "d"};String[] arr2 = {"d", "e", "f", "g"};Stream<String> stream1 = Stream.of(arr1);Stream<String> stream2 = Stream.of(arr2);// concat:合并两个流 distinct:去重List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());// limit:限制从流中获得前n个数据List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());// skip:跳过前n个数据List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());System.out.println("流合并:" + newList);// 流合并:[a, b, c, d, e, f, g]System.out.println("limit:" + collect);// limit:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]System.out.println("skip:" + collect2);// skip:[3, 5, 7, 9, 11]
}

八、总结

待续

更多推荐

Java Stream流操作

本文发布于:2023-12-03 07:05:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1652462.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:操作   Java   Stream

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!