java - streams 流

table of Contents

Overview

Stream operation steps

Create Stream

Intermediate operation

Terminate operation

stream practice


Overview

Streams are data channels, used to manipulate the sequence of elements generated by data sources (collections, arrays, etc.). Collections pay attention to data, and streams pay attention to calculations!

  1.   stream itself does not store elements
  2.   stream will not change the original data object, it will return a stream holding the result
  3.   Stream operations are lazily loaded, they will not be needed until the results are needed

Stream operation steps

  1. Create Stream: a data source (collection, array), get a stream
  2. Intermediate operation: data processing of the data source
  3. Terminate operation: return a new desired result

Code cloud address: https://gitee.com/bufanli/java8-demo.git

Create Stream

package cn.bufanli.stream;

import cn.bufanli.pojo.Employee;
import org.junit.Test;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Stream;
/**
 * @author BuShuangLi
 * @date 2019/3/11
 * 一、Stream的操作步骤
 * 1.创建stream
 * 2.中间操作
 * 3.终止操作(产生所需要的结果)
 */
public class StreamTest01 {
     /**
      * 创建Stream的方法
      */
     @Test
     public void test02() {
          //1.可以通过Collection 系列集合提供的  串行流 -->Stream() 或 并行流-->parallelStream();
          ArrayList<String> objects = new ArrayList<>();
          Stream<String> stream = objects.stream();
          //2.通过arrays 中的静态方法
          Employee[] emps=new Employee[10];
          Arrays.stream(emps);
          //3.通过Stream类中的静态方法
          Stream<String> aa = Stream.of("aa", "bb", "cc");
          //创建无限流
          //迭代 从0 开始进行+2操作 只需要前10个如果把limit去掉就会无限的输出
          Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
          iterate.limit(10).forEach(System.out::println);
          //生成
          Stream.generate(()->Math.random()*19).limit(5).forEach(System.out::println);
     }
}

Intermediate operation

 

  /**
      * 数据集合
      */
     List<Employee> employees = Arrays.asList(
              new Employee("张三", 36, 8899.99, Employee.Status.FREE),
              new Employee("李四", 25, 4499.99, Employee.Status.BUSY),
              new Employee("王五", 15, 5599.99, Employee.Status.VOCATION),
              new Employee("王五", 15, 5599.99, Employee.Status.FREE),
              new Employee("赵六", 35, 3399.99, Employee.Status.BUSY)

     );
     /*--------------------中间操作start--------------------*/

     /**
      * 中间操作
      * 内部迭代:Stream API完成
      * 筛选与切片
      * filter--接受lambda,从流中排出某些元素
      * limit--截断流,使其元素不超过指定数量
      * skip(n)--跳过元素,返回一个扔掉了n个元素的流,若流中的元素不足n个,则返回一个空流,与limit互补
      * distinct--筛选,通过流所生成的hashCode() 和equals() 去出重复元素
      */
     @Test
     public void test02() {
          //filter年龄大于38取前四个
          employees.stream()
                   //中间操作 如果没有终止操作,中间操作不会执行
                   .filter(employee -> employee.getAge() > 22)
                   //终止操作 在终止操作执行后一次性全部处理,成为惰性求值
                   .forEach(System.out::println);
          System.out.println("-----------------");

          //limit 年龄大于222 取前2个
          employees.stream().filter(e -> e.getAge() > 2).limit(2).forEach(System.out::println);
          System.out.println("-----------------");

          //skip  年龄大于2 取前四个 跳过前两个
          employees.stream().filter(e -> e.getAge() > 2).limit(4).skip(2).forEach(System.out::println);
          System.out.println("-----------------");

          //distinct 去重 通过hashCode() 和equals()来去重,需要重写实体的hashCode() 和equals()方法
          employees.stream().filter(e -> e.getAge() > 2).limit(6).skip(2).distinct().forEach(System.out::println);


     }

     /**
      * 映射
      * map--接受lambda,将元素转换为其他形式或提取信息.接受一个函数作为参数,
      * 该函数会被应用到每个元素上并将其映射成一个新的元素
      * flatMap--接受一个函数作为参数,将流中的每个值都换成另一个流,然后把所有的流连接成一个流
      */
     @Test
     public void test03() {
          List<String> strings = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
          strings.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
          System.out.println("-----------------");
          employees.stream().map(Employee::getName).distinct().forEach(System.out::println);
          System.out.println("-----------------");
          Stream<Stream<Character>> streamStream = strings.stream().map(x -> getCharacterStream(x));
          streamStream.forEach(s -> {
               s.forEach(System.out::println);
          });
          System.out.println("-----------------");
          //相当于上面
          strings.stream().flatMap(x -> getCharacterStream(x)).forEach(System.out::println);
     }

     public Stream<Character> getCharacterStream(String str) {
          ArrayList<Character> strings = new ArrayList<>();
          for (Character c : str.toCharArray()) {
               strings.add(c);
          }
          return strings.stream();
     }

     /**
      * 排序
      * sorted()--自然排序(Comparable)
      * sorted(Comparator com)--定制排序
      */
     @Test
     public void test04() {
          List<String> strings = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
          //自然排序
          strings.stream().sorted().forEach(System.out::println);
          System.out.println("-----------------");
          //定制排序
          employees.stream().sorted((e1, e2) -> {
               if (e1.getAge().equals(e2.getAge())) {
                    return e1.getName().compareTo(e2.getName());
               } else {
                    return e1.getAge().compareTo(e2.getAge());
               }
          }).forEach(System.out::println);


     }
     

Terminate operation

/**
      * 终止操作
      */
     /**
      * 查找与匹配
      * allMatch-检查是否匹配所有元素
      * anyMatch-检查是否至少匹配一个元素
      * noneMatch-检查是否没有匹配所有元素
      * findFirst-返回第一个元素
      * findAny-返回当前流中的任意元素
      * count-返回流中元素的总个数
      * max-返回流中的最大值
      * min-返回流中最小值
      */
     @Test
     public void test05() {
          //是不是匹配所有值
          boolean b = employees.stream()
                   .allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
          System.out.println(b);
          //至少匹配一个元素
          boolean b1 = employees.stream().anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
          System.out.println(b1);
          //没有匹配所有元素
          boolean b2 = employees.stream().noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
          System.out.println(b2);
          //返回第一个元素   .sorted((eOne, eTwo) -> -Double.compare(eOne.getSalary()  " - " 排序的顺序
          Optional<Employee> first = employees.stream()
                   .sorted((eOne, eTwo) -> -Double.compare(eOne.getSalary(), eTwo.getSalary()))
                   .findFirst();
          System.out.println(first.get());

     }
     @Test
     public void test06(){
          //count
          System.out.println(employees.stream().count());
          //max
          Optional<Employee> max = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
          System.out.println(max.get());
          //min
          Optional<Double> min = employees.stream().map(Employee::getSalary).min(Double::compareTo);
          System.out.println(min.get());
     }
     /**
      * 归约
      * reduce(T identity,BinaryOperator) /reduce(BinaryOperator) -可以将流中元素元素反复结合起来,得到一个值
      */
     @Test
     public void test07(){
          List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 23, 43, 66);
          Integer reduce = integers
                   .stream()
                   //先把0,作为x再从流中取出一个数据为y,然后将结果最为x再从流中去....
                   .reduce(0, (x, y) -> x + y);
          System.out.println(reduce);

          //累计算出当前工资的总和 因为没有起始值
          Optional<Double> reduce1 = employees.stream().map(Employee::getSalary).reduce(Double::sum);
          System.out.println(reduce1.get());
     }
     /**
      * 收集
      * collect--将流转换为其他形式,接受一个Collector接口实现,用于Stream中元素做汇总的方法
      */
     @Test
     public void test08(){
          //收集当前员工所有的名字收集然后放到集合当中
          List<String> collect = employees.stream().map(Employee::getName).collect(Collectors.toList());
          collect.forEach(System.out::println);
          //总和
          Double sum = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));
          System.out.println(sum);
          //最大值
          Optional<Employee> max = employees.stream()
                   .collect(Collectors.maxBy((a, b) -> Double.compare(a.getSalary(), b.getSalary())));
          System.out.println(max.get());
          //最小值
          Optional<Double> min = employees.stream().map(Employee::getSalary)
                   .collect(Collectors.minBy(Double::compareTo));
          System.out.println(min.get());
          //分组
          Map<Employee.Status, List<Employee>> group = employees.stream().collect(Collectors.groupingBy(Employee::getStatus));
          System.out.println(group);
          //多几分组
          Map<Employee.Status, Map<String, List<Employee>>> groups = employees.stream()
                   .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                        if (e.getAge() >= 35) {
                             return "青年";
                        } else if (e.getAge() <= 50) {
                             return "青年";
                        } else {
                             return "老年";

                        }
                   })));

          System.out.println(groups);
          //分区 满足条件一个区,不满足条件的一个区
          Map<Boolean, List<Employee>> collect1 = employees.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 5000));
          System.out.println(collect1);

          //获取总和 平均 ..其他方式
          DoubleSummaryStatistics collect2 = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
          System.out.println(collect2.getAverage());
          System.out.println(collect2.getCount());
          System.out.println(collect2.getMax());
          //.....
          //连接
          String collect3 = employees.stream()
                   .map(Employee::getName)
                   //[张三,李四,王五,王五,赵六]
                   .collect(Collectors.joining(",","[","]"));
          System.out.println(collect3);

     }

stream practice

Entity class

package cn.bufanli.pojo;
//交易员类
public class Trader {

	private String name;
	private String city;

	public Trader() {
	}

	public Trader(String name, String city) {
		this.name = name;
		this.city = city;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	@Override
	public String toString() {
		return "Trader [name=" + name + ", city=" + city + "]";
	}

}
package cn.bufanli.pojo;
//交易类
public class Transaction {

	private Trader trader;
	private int year;
	private int value;

	public Transaction() {
	}

	public Transaction(Trader trader, int year, int value) {
		this.trader = trader;
		this.year = year;
		this.value = value;
	}

	public Trader getTrader() {
		return trader;
	}

	public void setTrader(Trader trader) {
		this.trader = trader;
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Transaction [trader=" + trader + ", year=" + year + ", value="
				+ value + "]";
	}

}

Practice class

package cn.bufanli.stream;

import cn.bufanli.pojo.Employee;
import cn.bufanli.pojo.Trader;
import cn.bufanli.pojo.Transaction;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author BuShuangLi
 * @date 2019/3/12
 */
public class StreamAPI {
     /**
      * 1.给定一个数字列表,如何返回一个由每个数的平方构成的列表,
      * 给定1,2,3,4,5 返回 2,4,9,16,25
      */
     @Test
     public void test01() {
          List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
          ArrayList<Integer> objects = new ArrayList<>();
          List<Integer> collect = nums.stream().map(x -> x * x).collect(Collectors.toList());
          System.out.println(collect);

     }

     /**
      * 数据集合
      */
     List<Employee> employees = Arrays.asList(
              new Employee("张三", 36, 8899.99, Employee.Status.FREE),
              new Employee("李四", 25, 4499.99, Employee.Status.BUSY),
              new Employee("王五", 15, 5599.99, Employee.Status.VOCATION),
              new Employee("王五", 15, 5599.99, Employee.Status.FREE),
              new Employee("赵六", 35, 3399.99, Employee.Status.BUSY)

     );

     /**
      * 怎样用map和reduce方法数一数流中有多少个Employee
      */
     @Test
     public void test02() {
          Optional<Integer> reduce = employees.stream()
                   .map(e -> 1)
                   .reduce(Integer::sum);
          System.out.println(reduce.get());
     }

     List<Transaction> transactions = null;

     @Before
     public void before() {
          Trader raoul = new Trader("Raoul", "Cambridge");
          Trader mario = new Trader("Mario", "Milan");
          Trader alan = new Trader("Alan", "Cambridge");
          Trader brian = new Trader("Brian", "Cambridge");

          transactions = Arrays.asList(
                   new Transaction(brian, 2011, 300),
                   new Transaction(raoul, 2012, 1000),
                   new Transaction(raoul, 2011, 400),
                   new Transaction(mario, 2012, 710),
                   new Transaction(mario, 2012, 700),
                   new Transaction(alan, 2012, 950)
          );
     }

     /**
      * //1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
      */
     @Test
     public void test03() {
          List<Transaction> collect = transactions.stream().filter(t -> t.getYear() == 2011)
                   .sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
                   .collect(Collectors.toList());
          System.out.println(collect);
     }

     /**
      * //2. 交易员都在哪些不同的城市工作过?
      */
     @Test
     public void test04() {
          List<String> collect = transactions.stream()
                   .map(t -> t.getTrader().getCity())
                   .distinct()
                   .collect(Collectors.toList());
          System.out.println(collect);

     }

     /**
      * //3. 查找所有来自剑桥的交易员,并按姓名排序
      */
     @Test
     public void test05() {
          // Cambridge
          List<Transaction> collect = transactions.stream()
                   .filter(x -> "Cambridge".equals(x.getTrader().getCity()))
                   .sorted((x, y) -> {
                        return x.getTrader().getName().compareTo(y.getTrader().getName());
                   }).distinct().collect(Collectors.toList());
          System.out.println(collect.size());
     }

     /**
      * //4. 返回所有交易员的姓名字符串,按字母顺序排序
      */
     @Test
     public void test06() {
          transactions.stream()
                   .map(x -> x.getTrader().getName())
                   .sorted()
                   .forEach(System.out::println);
          System.out.println("------------------");
          String collect = transactions.stream()
                   .map(x -> x.getTrader().getName())
                   .sorted()
                   .collect(Collectors.joining());
          System.out.println(collect);
          System.out.println("------------------");
          String collect1 = transactions.stream()
                   .flatMap(t -> filterCharacter(t.getTrader().getName()))
                   .sorted((x1, x2) -> x1.compareToIgnoreCase(x2)).collect(Collectors.joining());
          System.out.println(collect1);


     }

     public Stream<String> filterCharacter(String str){
          List<String> strings = new ArrayList<>();
          for (Character c : str.toCharArray()) {


               strings.add(c.toString());
          }
          return strings.stream();
     }
     /**
      * //5. 有没有交易员是在米兰工作的?
      */
     @Test
     public void test07() {
          boolean milan = transactions.stream().anyMatch(t -> t.getTrader().getCity().equals("Milan"));
          System.out.println(milan);
     }
     /**
      * //6. 打印生活在剑桥的交易员的所有交易额
      */
     @Test
     public void test08() {
          transactions.stream()
                   .filter(x->x.getTrader().getCity().equals("Cambridge"))
                   .map(t->t.getValue())
                   .forEach(System.out::println);

     }
     /**
      * //7. 所有交易中,最高的交易额是多少
      */
     @Test
     public void test09() {
          Optional<Integer> max = transactions.stream()
                   .map(x -> x.getValue())
                   .max((x1, x2) -> +Double.compare(x1, x2));
          System.out.println(max.get());

     }
     /**
      * //8. 找到交易额最小的交易
      */
     @Test
     public void test10() {
          Optional<Integer> min = transactions.stream()
                   .map(x -> x.getValue())
                   .min((x1, x2) -> +Double.compare(x1, x2));
          System.out.println(min.get());
          Optional<Integer> max = transactions.stream()
                   .map(x -> x.getValue())
                   .max((x1, x2) -> -Double.compare(x1, x2));
          System.out.println(max.get());

     }
}

Parallel stream and sequential stream

Parallel streaming is to divide a content into multiple blocks of data, and use different threads to process each data block stream separately

Optimized in java 8, we can easily manipulate the data. It is more efficient when the amount of data is large;

Stream API can declaratively switch between parallel stream and sequential stream through parallel() and sequential(); the bottom layer is Frok/Join

package cn.bufanli.stream;

import org.junit.Test;

import java.time.Duration;
import java.time.Instant;
import java.util.stream.LongStream;

/**
 * @author BuShuangLi
 * @date 2019/3/12
 */
public class StreamParallel {
     /**
      * java 8 并行流
      */
     @Test
     public void test02() {
          Instant start = Instant.now();

          //顺序流
          LongStream.rangeClosed(0, 100000000000L)
                   .reduce(0, Long::sum);
          Instant end = Instant.now();
          System.out.println("串行流耗时:" + Duration.between(start, end).toMillis());
          //控制台打印--串行流耗时:133177

          Instant start2 = Instant.now();

          //并行流
          LongStream.rangeClosed(0, 100000000000L)
                   .parallel()
                   .reduce(0, Long::sum);
          Instant end2 = Instant.now();

          System.out.println("并行行流耗时:" + Duration.between(start2, end2).toMillis());
          //控制台打印--并行流耗时:73396

     }
}

 

Guess you like

Origin blog.csdn.net/adminBfl/article/details/88400948