Stream 将要处理的元素集合看作一种流,在流的过程中,借助
Stream API
对流中的元素进行操作,比如:筛选、排序、聚合等。
Stream可以由数组或集合创建,对流的操作分为两种:
中间操作
:·每次返回一个新的流,可以有多个。终端操作
:每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。Stream
的几个特点:
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,3,5,8,6,7,9);
// 遍历输出符合条件的值
list.stream().filter(l -> l > 5).forEach(System.out::println);
}
}
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,3,5,8,6,7,9);
// 匹配第一个
Optional<Integer> findFirst = list.stream().filter(l -> l > 5).findFirst();
// 匹配任意(适用于并行流)
Optional<Integer> findAny = list.parallelStream().filter(l -> l > 6).findAny();
// 是否包含符合特定条件的元素
boolean anyMatch = list.stream().anyMatch(l -> l > 6);
}
}
stream
和parallelStream
的简单区分:
stream
是顺序流,由主线程按顺序对流执行操作,
parallelStream
是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,3,5,8,6,7,9);
list.stream.filter(l -> l > 5).forEach(System.out::println);
}
}
max/min
public class StreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
Optional<String> max = list.stream().max(Comparator.comparing(String::length));
Optional<String> min = list.stream().min(Comparator.comparing(String::length));
System.out.println("最长的字符串:" + max.get());
System.out.println("最短的字符串:" + min.get());
}
}
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 3);
// 自然排序
Optional<Integer> max1 = list.stream().max(Integer::compareTo);
// 自定义排序
Optional<Integer> max2 = list.stream().max((l1, l2) -> l1.compareTo(l2));
/*简写为上面这个
Optional max2 = list.stream().max(new Comparator() {
@Override
public int compare(Integer l1, Integer l2) {
return l1.compareTo(l2);
}
});*/
}
}
count
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 5);
long count = list.stream().filter(x -> x > 5).count();
System.out.println("list中大于5的元素个数:" + count);
}
}
映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。分为map
和flatMap
:
map
:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。flatMap
:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。map
public class StreamTest {
public static void main(String[] args) {
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);
System.out.println("每个元素+3:" + intListNew);
}
}
flatMap
public class StreamTest {
public static void main(String[] args) {
List<String> list = Arrays.asList("m,k,l,a","1,3,5,7");
List<String> listNew = list.stream().flatMap(s -> {
// 将每个元素转换成一个stream
String[] split = s.split(",");
Stream<String> s2 = Arrays.stream(split);
return s2;
}).collect(Collectors.toList());
System.out.println("处理前的集合:" + list);
System.out.println("处理后的集合:" + listNew);
}
}
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
// 求和方式1
Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
// 求和方式2
Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
// 求和方式3 reduce的第一个参数是Integer类型
Integer sum3 = list.stream().reduce(0, Integer::sum);
// 求乘积
Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
// 求最大值方式1
Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
Optional<Integer> max1= list.stream().reduce(Integer::max);
// 求最大值写法2
Integer max2 = list.stream().reduce(0, Integer::max);
System.out.println("sum--->" + sum.get() + "," + "sum2--->" + sum2.get() + "," + "sum3--->" + sum3);
System.out.println("list求积:" + product.get());
System.out.println(max1.get()+"===================");
System.out.println("max--->" + max.get() + " max2------->" + max2);
}
}
collect
主要依赖java.util.stream.Collectors类内置的静态方法。
实体类:(后面都可以用到)
package com.example.juc.stream;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name; // 姓名
private int salary; // 薪资
private int age; // 年龄
private String sex; //性别
private String area; // 地区
public Person(String name, int salary, String sex, String area) {
this.name = name;
this.salary = salary;
this.sex = sex;
this.area = area;
}
}
public class StreamTest {
public static void main(String[] args) {
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());
Set<Integer> set = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
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"));
Map<?, Person> map = personList.stream().filter(p -> p.getSalary() > 8000)
.collect(Collectors.toMap(Person::getName, p -> p));
System.out.println("toList:" + listNew);
System.out.println("toSet:" + set);
System.out.println("toMap:" + map);
}
}
public class StreamTest {
public static void main(String[] args) {
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"));
// 求总数
Long count = personList.stream().collect(Collectors.counting());
long count1 = personList.stream().count();
// 求平均工资
Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
Integer sumSalary = personList.stream().map(Person::getSalary).reduce(0, Integer::sum);
long l = sumSalary / count1;
// 求最高工资
Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
Integer max1 = personList.stream().map(Person::getSalary).reduce(2, Integer::max);
// 求工资之和
Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
// 一次性统计所有信息
DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println("员工总数:" + count);
System.out.println("count1----------->"+count1);
System.out.println("员工平均工资:" + average);
System.out.println("l----------->"+l);
System.out.println("员工最高工资:"+max.get());
System.out.println("max1------------->"+max1);
System.out.println("员工工资总和:" + sum);
System.out.println("sumSalary----------->"+sumSalary);
System.out.println("员工工资所有统计:" + collect);
System.out.println("---------------------------------------");
personList.stream().map(Person::getSalary).forEach(System.out::println);
}
}
public class StreamTest {
public static void main(String[] args) {
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"));
Map<String, List<Person>> sexGroup = personList.stream().collect(Collectors.groupingBy(Person::getSex));
Map<String, Map<String, List<Person>>> areaGroup = personList.stream().collect(Collectors.groupingBy(Person::getSex,Collectors.groupingBy(Person::getArea)));
System.out.println(areaGroup);
}
}
public class StreamTest {
public static void main(String[] args) {
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"));
String stringStream = personList.stream().map(n -> n.getName()).collect(Collectors.joining("--"));
String collect = personList.stream().map(Person::getSex).collect(Collectors.joining("-"));
}
}
Collectors
类提供的reducing
方法,相比于stream
本身的reduce
方法,增加了对自定义归约的支持。
public class Demo06 {
public static void main(String[] args) {
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"));
Integer reduce = personList.stream().map(Person::getSalary).reduce(1, Integer::sum);
Integer collect = personList.stream().collect(Collectors.reducing(1, Person::getSalary, Integer::sum));
}
}
sorted,中间操作。有两种排序:
public class Demo07 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<Person>();
personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
personList.add(new Person("Tom", 8900, 27, "male", "Washington"));
personList.add(new Person("Jack", 9100, 23, "male", "Washington"));
personList.add(new Person("Lily", 8800, 26, "male", "New York"));
personList.add(new Person("Alisa", 9200, 22, "female", "New York"));
// //按照工资顺序排列
List<String> collect = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName).collect(Collectors.toList());
// //按照工资倒序排列
// List collect1 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed()).map(Person::getName).collect(Collectors.toList());
List<String> s = personList.stream().sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName).collect(Collectors.toList());
List<String> c= personList.stream().sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge).reversed()).map(Person::getName).collect(Collectors.toList());
}
}
public class StreamTest {
public static void main(String[] args) {
String[] s1 = { "a", "b", "c", "d" };
String[] s2 = { "d", "e", "f", "g" };
Stream<String> stream1 = Stream.of(s1);
Stream<String> stream2 = Stream.of(s2);
// 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);
System.out.println("limit:" + collect);
System.out.println("skip:" + collect2);
}
}