流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还可以透明地并行处理,你无需写任何多线程代码了。 通过parallelStream或者parallel(内部调用join/fork)就能实现并行操作,需要注意的是线程安全问题及合适的方式采用并行。当然并不是所有并行性能就会好,这里涉及到装箱、拆箱、核数、当前cpu使用率等等。
public class StreamTest extends Java8BaseTest { @Test public void test() { //1 筛选重量大于3 2 映射获取颜色 3 去重 4 排序 5 跳过 6 截流 7 合并 //那么点代码 干了这么多事情,想想,要是不用stream,做这些事情需要多少代码 List<String> colors = apples.stream().filter((Apple a) -> a.getWeight() > 3) .map(Apple::getColor).distinct().sorted().skip(0).limit(3).collect(toList()); System.out.println(colors.toString()); Assert.assertEquals(colors.size(), 3); Assert.assertEquals(colors.get(0), "green"); // List转成数组 Apple[] array = apples.toArray(new Apple[0]); // 输出数组 for (int i = 0; i < array.length; i++) { System.out.println("array--> " + array[i]); } } @Test public void matchTest() { //.allMatch().noneMatch() 匹配 返回true 所以直接结束 Assert.assertEquals( apples.stream().anyMatch(a -> a.getColor().equals("green")), true); } @Test public void findTest() { //.findAny() 查找 Assert.assertEquals(apples.stream().findFirst().get().getColor(), "red"); } @Test public void reduceTest() { //reduce 让我们计算下价格总和 Apple c = new Apple(0, 0.0, ""); double allPrice = apples.stream().reduce(c, (Apple a, Apple b) -> { a.setPrice(a.getPrice() + b.getPrice()); return a; }).getPrice(); //使用mapToDouble的sum方法也可以实现数值相加,allPrice1这里的值为10.700000000001 精度问题 使用decimal可以解决 double allPrice1 = apples.stream().mapToDouble(Apple::getPrice).sum(); Assert.assertEquals(allPrice == 10.7, true); } @Test public void flatMapTest() { //flatMap的作用是将多个流合并成一个流 List<List<Apple>> appless = new ArrayList<>(); appless.add(apples); appless.add(apples); //获取一个流后还可以使用test1中的操作进行过滤 是否很简洁 List<Apple> newApples = appless.stream().map((List<Apple> a) -> a.toArray(new Apple[a.size()])) .flatMap(Arrays::stream).collect(toList()); Assert.assertEquals(newApples.size(), apples.size() * 2); } @Test public void pythagoreanTripleTest() { //在1-100内的勾股数值 比如 3*3+4*4=5*5 这类数据 Stream<int[]> pythagoreanTriples = //生成1-100的int流 boxed将原始流转换成一般流(不然后面操作返回数据格式就不符合而报错) 即转换为Stream<Integer> IntStream.rangeClosed(1, 100).boxed() //因为内置还有个集合,需要使用flatMap方法将其变为一个集合,合并多个集合为一个 .flatMap(a -> //生成a-100的int流 IntStream.rangeClosed(a, 100) //过滤勾股数据 .filter(b -> Math.sqrt(a * a + b * b) % 1 == 0) //将Integer转换为数组 这里需要使用mapToObj 否则只能发挥Integer .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)}) ); pythagoreanTriples .forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2])); } @Test public void groupTest() { //分组操作 //按颜色对apples进行分组 返回Map<String,List<Apple>> 如果不用流的话,试想下该怎么做 //就一行代码搞定,就问简洁不简洁 // 当然除了groupingBy 还有maxBy(最大 内部其实是通过reducing) minBy(最小) summingInt(求和) summarizingInt(包括求和,平均等等都在里面) joining(连接字符串) reducing 很多方法,自行查看Collectors类 Map<String, List<Apple>> maps = apples.stream().collect(groupingBy(Apple::getColor)); System.out.println(maps.toString()); Assert.assertEquals(maps.size(), 3); //groupingBy 接收的是Function 即可以返回其他的值,那么就可以在这里做些内容,比如: //red、yellow 是我最喜欢的,返回 like ,其他为 hate Map<String, List<Apple>> maps1 = apples.stream().collect(groupingBy((Apple a) -> { if (a.getColor().equals("red") || a.getColor().equals("yellow")) { return "like"; } else { return "hate"; } })); System.out.println(maps1.toString()); //groupingBy 还可以接收第二个为Collector的参数代表map中的value值 好吗~ 那么基本上 Collectors方法都可以使用 // 比如 再传一个groupingBy进行二级分组(循环下去就是N级分组) 无非就是Map又包含了Map // 比如 传一个counting计算个数 Map<String, Long> maps2 = apples.stream().collect( groupingBy(Apple::getColor, counting())); System.out.println(maps2.toString()); } @Test public void joinTest() { //查看joining 可知 只能接受字符串 跟我原先想的有些出入 我以为是调用类的.toString()方法获取数据 //下面三种结果都一样,不过 joining 使用的是StringBuilder,所以方法多种多样,joining性能最佳 String str = apples.stream().map(Apple::getColor).collect(joining()); String str1 = apples.stream().map(Apple::getColor) .collect(reducing((s1, s2) -> s1 + s2)).get(); String str2 = apples.stream() .collect(reducing("", Apple::getColor, (s1, s2) -> s1 + s2)); Assert.assertEquals(str, str1); Assert.assertEquals(str, str2); } }