import lombok.Data;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
/**
* 官方api文档:https://www.oracle.com/java/technologies/javase/8-whats-new.html
* 记录stream的用法
* 简介:
* Stream是Java8 新增的流特性,目的是让程序员写出高效率、干净、简洁的代码
* Stream类似于SQL语句,可以对代码进行集合运算和表达
* Stream就是把元素看成一种流,流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
* @author Three soil
* @Date 2021/4/12
**/
public class StreamInJava {
@Test
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("1");
list1.add("2");
list1.add("3");
list1.add("5");
list1.add("6");
List<String> list2 = new ArrayList<>();
list2.add("2");
list2.add("3");
list2.add("7");
list2.add("8");
// 交集(直接使用 retainAll() 方法效率更高)
List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
System.out.println("---交集 intersection---");
intersection.parallelStream().forEach(System.out :: println);
//streamBase();
}
/**
* stream的基本用法
*/
private static void streamBase(){
// 表达式:
List<Person> personList = new ArrayList<>();
// 初始化数据
personList.add(new Person("张三", 18, 1));
personList.add(new Person("李四", 20, 2));
personList.add(new Person("王五", 16, 2));
personList.add(new Person("赵六", 32, 1));
personList.add(new Person("陆七", 19, 2));
personList.add(new Person("陆八", 19, 1));
personList.add(new Person("陆九", 19, 4));
personList.add(new Person("陆十", 19, 3));
// 基础接口方法
/**
* Iterator<T> iterator();//迭代器
*
* Spliterator<T> spliterator();//分路器
*
* boolean isParallel(); //判断是否是并行化流
*
* S sequential(); //将流串行化
*
* S parallel(); //将流并行化
*
* S unordered(); //解除有序流的顺序限制,发挥并行处理的性能优势
*
* S onClose(Runnable closeHandler);//一次性
*
* void close();
* */
// 1.串行流和并行流
// 除了直接创建并行流,还可以通过parallel()把顺序流转换成并行流:
Optional<Person> findFirst = personList.stream().parallel().filter(x->x.getAge()>6).findFirst();
testStream(personList);
testParallelStream(personList);
// 2.中间操作
testFilter(personList); // 2.1 filter过滤操作
testMap(personList); // 2.2 map抽取内容生成集合
testSorted(personList); // 2.3 sorted排序
testLimit(personList); // 2.4 limit 限制查询条目数
testDistinct(personList); // 2.5 distinct 去重
testSkip(personList); // 2.6 skip 跳过
testMapTo(personList); // 2.7 mapTo 统计
testCollect(personList); // 2.8 collect规约操作
testPeek(personList); // 2.9 peek消费
// 3.终止操作
}
// 1.1 串行流
private static void testStream(List<Person> personList){
System.out.println("1.1 串行流 ->");
long startTime = System.currentTimeMillis();
personList.stream().forEach(person -> System.out.println(person));
long endTime = System.currentTimeMillis();
System.out.println("stream consume time -> " + (endTime - startTime));
}
// 1.2 并行流
private static void testParallelStream(List<Person> personList){
System.out.println("1.2 并行流 ->");
long startTime = System.currentTimeMillis();
personList.parallelStream().forEach(person -> System.out.println(person));
long endTime = System.currentTimeMillis();
System.out.println("stream consume time -> " + (endTime - startTime));
}
// 2.1 filter 过滤(保留条件相同的数据 如下(sex==1)就保留sex=1的数据)
private static void testFilter(List<Person> personList){
System.out.println("2.1 filter过滤 ->");
personList = personList.stream().filter(person -> person.getSex()==1).collect(Collectors.toList());
System.out.println(personList);
}
// 2.2 map抽取内容生成集合
private static void testMap(List<Person> personList){
System.out.println("2.2 map抽取内容生成集合 ->");
List<String> nameList = personList.stream().map(Person::getName).collect(Collectors.toList());
nameList.stream().forEach(System.out::print);// 该种打印方式会将数据打印在同一行
}
// 2.3 sorted 排序(进阶用法,多个字段排序)
private static void testSorted(List<Person> personList){
System.out.println("2.3 sorted 排序 ->");
System.out.println("------ 按年龄升序排序 ------");// 默认升序
List<Person> sortedList = personList.stream().sorted(Comparator.comparing(Person::getAge)).collect(Collectors.toList());
sortedList.stream().forEach(person -> System.out.println(person));
System.out.println("------ 按年龄降序排序 ------");// reversed是降序
List<Person> sortedDescList = personList.stream().sorted(Comparator.comparing(Person::getAge).reversed()).collect(Collectors.toList());
sortedDescList.stream().forEach(person -> System.out.println(person));
}
// 2.4 limit 限制查询条目数(与2.6 skip 跳过元素结合使用可以做出简易分页。具体百度: java8的skip)
private static void testLimit(List<Person> personList){
System.out.println("2.4 limit 限制查询条目数 ->");
List<Person> limitList = personList.stream().limit(2).collect(Collectors.toList());
limitList.stream().forEach(person -> System.out.println(person));
}
// 2.5 distinct 去重
private static void testDistinct(List<Person> personList){
System.out.println("2.5 distinct 去重 ->");
List<Integer> distinctList = personList.stream().map(Person::getAge).distinct().collect(Collectors.toList());
distinctList.stream().forEach(integer -> System.out.println(integer));
}
/**
* 2.4 limit限制查询条目数 与 2.6 skip跳过元素 结合使用可以做出简易分页。具体百度: java8的skip
*/
// 2.6 skip 跳过元素
private static void testSkip(List<Person> personList){
System.out.println("2.6 skip 跳过元素 ->");
List<Person> skipList = personList.stream().skip(3).collect(Collectors.toList());
skipList.stream().forEach(person -> System.out.println(person));
}
// 2.7 mapTo统计 flatMapTo为更高层次用法,将在stream进阶进行示例
private static void testMapTo(List<Person> personList){
System.out.println("2.7 mapTo统计 ->");
IntSummaryStatistics intSummaryStatistics = personList.stream().mapToInt(Person::getAge).summaryStatistics();
System.out.println("总条目数:"+intSummaryStatistics.getCount());
System.out.println("年龄求和:"+intSummaryStatistics.getSum());
System.out.println("最大值:"+intSummaryStatistics.getMax());
System.out.println("最小值:"+intSummaryStatistics.getMin());
System.out.println("平均值:"+intSummaryStatistics.getAverage());
}
// 2.8 collect 规约操作
public static void testCollect(List<Person> personList) {
System.out.println("2.8 collect规约操作 ->");
String names = personList.stream().map(Person::getName).collect(Collectors.joining(","));
System.out.println(names);
}
// 2.9 peek 消费 如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。
public static void testPeek(List<Person> personList){
System.out.println("2.9 peek消费 ->");
personList.stream().peek(person -> person.setName("123")).forEach( s-> System.out.println(s));
}
// 3.1 匹配、聚合操作(流的终止操作)
/**
* allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
* noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
* anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
* findFirst:返回流中第一个元素
* findAny:返回流中的任意元素
* count:返回流中元素的总个数
* max:返回流中元素最大值
* min:返回流中元素最小值
*/
public static void testTerminateOperation(){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true
Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1
long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1
}
//----------------------------------------------------------------------------------------------------------------------
/**
* stream的进阶用法
*/
@Test
public void streamAdvanced(){
}
/**
* Person实体类
*/
@Data
static class Person{
String name;
Integer age;
Integer sex;
Person(){}// 构造函数(构造方法)
Person(String name,Integer age,Integer sex){// 重载
this.name = name;
this.age = age;
this.sex = sex;
}
}
}