Java8实战之(四)使用流

4 使用流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.1 筛选和切片

在这里插入图片描述
谓词做筛选(忽略流中的数据),截短到指定长度教切片

4.1.1 用谓词筛选

在这里插入图片描述

4.1.2 筛选各异的元素

在这里插入图片描述
在这里插入图片描述

4.1.3 截短流

在这里插入图片描述
在这里插入图片描述

4.1.4 跳过元素

在这里插入图片描述
在这里插入图片描述

4.2 映射

一个非常常见的映射就是获取对象中的属性值,比如在sql中选择一列,Streamapi也提供了map和flatmap方法提供了类似的工具

4.2.1 对流中每一个元素应用函数

在这里插入图片描述

        List<Dish> dishes = Arrays.asList(new Dish("asda",false,1, Dish.Type.MEAT),new Dish("1",false,1, Dish.Type.MEAT),new Dish("2",false,1, Dish.Type.MEAT));
        List<String> dishNames = dishes.stream().map((Dish dish) -> dish.getName()).collect(Collectors.toList())

在这里插入图片描述

        // 获取字符串长度
        List<String> words = Arrays.asList("a12","asd","lamdba","adsasd");
        List<Integer> wordsLength = words.stream().map(String::length).collect(Collectors.toList());

在这里插入图片描述
在这里插入图片描述

4.2.2 流的扁平化

扁平化就是将每个流化成单个流
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1.尝试使用map和Arrays.stream
首先你需要一个字符流,而不是数组流,有一个叫做Arrays.stream的方法可以接受一个数组并产生一个流。例如

        List<String> list1 = Arrays.asList("Hello", "World");
        // 以下代码报异常,因为map返回的是流的列表,并不是流的内容
        List<String> dd = list1.stream().map((String s) -> s.split(""))
                .map(Arrays::stream)
                .distinct()
                .collect(toList());

使用flatmap


        List<String> list1 = Arrays.asList("Hello", "World");
        List<String> dd = list1.stream().map((String s) -> s.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(toList());

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

4.3 测验

在这里插入图片描述

        // 你可以利用map方法的Lambda,接受一个数字,并返回该数字的平方的Lambda来ᝌ
        //解决这个问题。
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> squares =
                numbers.stream()
                        .map(n -> n * n)
                        .collect(toList());
        squares.forEach(item -> System.out.println(item));

在这里插入图片描述
在这里插入图片描述

        // 测验二
/*        给定两个数字列表,如何返回所有的数对呢?例如给定列表1[1, 2, 3]和表[3, 4],应
        该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]。为简单期起见,你可以用有两个元素的数组来代
        表数对。*/
        List<Integer> number1 = Arrays.asList(1,2,3);
        List<Integer> number2 = Arrays.asList(3,4);
        List<int[]> pairs =
                number1.stream()
                        .flatMap(i -> number2.stream()
                                .map(j -> new int[]{i,j})
                        )
                        .collect(toList());
        pairs.parallelStream().forEach((int[] i) -> System.out.println(i));

在这里插入图片描述

        // 测试三
        List<int[]> pairs1 =
                number1.stream()
                        .flatMap((Integer i) -> number2.stream()
                                // 过滤
                                .filter((Integer j) -> (i + j) % 3 == 0)
                                .map((Integer j) -> new int[]{i,j})
                        )
                        .collect(toList());
        System.out.println(pairs1);

4.4 查找和匹配

在这里插入图片描述

4.4.1 检查谓词是否至少匹配一个元素

说白了就是是否包含某个元素
anyMatch方法可以回答“流中是否有一个元素能匹配给定的谓词”。比如,你可以用它来看看菜单里面是否有素食可选择:

        // 检查谓词是否至少匹配一个元素
        if(dishes.stream().anyMatch(Dish::isVegetarian)){
            System.out.println("找到素食");
        }

4.4.2 检查谓词是否匹配所有元素

allMatch方法的工作原理和anyMatch类似,但它会看看流中的元素是否都能匹配给定的谓词。比如,你可以用它来看看菜品是否有利安全(即所有热量都低于1000卡路里)

        // 检查谓词是否匹配所有元素
        boolean isHealthy = dishes.stream().allMatch((Dish dish) -> dish.getCalories() < 1000);

在这里插入图片描述
在这里插入图片描述

4.4.3 查找元素

在这里插入图片描述

        // 查找元素
        Optional<Dish> dish =
                dishes.stream()
                        .filter(Dish::isVegetarian)
                        .findAny();

Optional简介
在这里插入图片描述
在这里插入图片描述

4.4.4 查找第一个元素

在这里插入图片描述

4.5 规约

在这里插入图片描述
在这里插入图片描述

4.5.1 元素求和

在这里插入图片描述

         // 求和
         int sumCalories = dishes.stream().map(Dish::getCalories).reduce(0,(int a,int b) -> {
             return a + b;
         });

4.5.2 最大值与最小值

在这里插入图片描述
在这里插入图片描述


         // 计算最大值
         Optional<Integer> maxCalories = dishes.stream().map(Dish::getCalories).reduce(Integer::max);
         Optional<Integer> minCalories1 = dishes.stream().map(Dish::getCalories).reduce((Integer x,Integer y) -> x < y ? x : y);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

        int dishNum = dishes.stream().map(d -> 1).reduce(0,Integer::sum);
        System.out.println(dishNum);

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.6 付诸实践

在本节中,你会将迄今学到的关于流的知付诸诸实践。我们来看一个不同的领域:执行交易的交易员。你的经理让你为八个查询找到答案。你能做到吗?
(1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。
(2) 交易员都在哪些不同的ۡ市工作过?
(3) 查找所有来自剑桥的交易员,并按ހ名排序。
(4) 返回所有交易员的姓名字符串,按字母顺序排序。
(5) 有没有交易员是在米兰工作的?
(6) 打印生活在剑桥的交易员的所有交易额。
(7) 所有交易中,最高的交易额是多少?
(8) 找到交易额最小的交易。

package com.java.lamdba.four;

import lombok.Data;

/**
 * 交易员类
 */
@Data
public class Trader {
    private final String name;
    private final String city;
    public Trader(String n, String c){
        this.name = n;
        this.city = c;
    }
}

package com.java.lamdba.four;

import lombok.Data;

/**
 * 交易类
 */
@Data
public class Transaction {
    private final Trader trader;
    private final int year;
    private final int value;
    public Transaction(Trader trader, int year, int value){
        this.trader = trader;
        this.year = year;
        this.value = value;
    }
}

package com.java.lamdba.four;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toSet;

/**
 * 测试类
 */
public class TradDemo {
    public static void main(String[] args) {
        Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brian = new Trader("Brian","Cambridge");
        List<Transaction> 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年的所有交易并按交易额排序(从低到高)
        List<Transaction> tr2011 = transactions.stream().filter(d -> d.getYear() == 2011)
                .sorted(Comparator.comparing(Transaction::getValue))
                .collect(Collectors.toList());

        // 2.交易员都在哪些不同的城市工作过
        List<String> cities = transactions.parallelStream().map((Transaction transaction) -> transaction.getTrader().getCity())
                .distinct()
                .collect(Collectors.toList());
        Set<String> cities1 =
                transactions.stream()
                        .map(transaction -> transaction.getTrader().getCity())
                        .collect(toSet());

        // 3.查找所有来自于剑桥的交易员,并按姓名排序
        List<Trader> traders = transactions.stream().map(Transaction::getTrader)
                .filter( d -> "Cambridge".equals(d.getCity()))
                .distinct()
                .sorted(Comparator.comparing(Trader::getName))
                .collect(Collectors.toList());

        // 4.返回所有交易员姓名的字符串并通过字母排序,按字母顺序排序
        String nameStr = transactions.stream().map((Transaction t) -> t.getTrader().getName())
                .distinct()
                .sorted()
                .reduce("",(String::concat));
        String nameStr1 = transactions.stream().map((Transaction t) -> t.getTrader().getName())
                .distinct()
                .sorted()
                .collect(Collectors.joining());

        // 5.有没有交易员是在米兰工作的
        boolean isMilan = transactions.stream().anyMatch(d -> d.getTrader().getCity().equals("Milan"));

        // 6.打印生活在剑桥的交易员的所有交易额
        transactions.stream().filter(item -> "Cambridge".equals(item.getTrader().getCity()))
                .map(item -> item.getValue())
                .forEach(item -> System.out.println("交易额为" + item));

        // 7. 所有交易中,最高的交易额是多少
        Optional<Integer> maxValue = transactions.stream().map(item -> item.getValue()).reduce(Integer::max);


        // 8. 所有交易中,最少的交易额是多少
        Optional<Integer> minValue = transactions.stream().map(item -> item.getValue()).reduce(Integer::min);

    }
}

4.7 数值流

在这里插入图片描述

4.7.1 原始类型流特化

IntStream,DoubleStream,LongStream作为原始类型特化流,顾名思义就是将流中的元素转成int,double,long,从而避免的装箱操作

  1. 映射到数值流
    在这里插入图片描述

  2. 转回对象流
    在这里插入图片描述

  3. 默认值OptionalInt
    在这里插入图片描述

4.7.2 数值范围

和数字打交道时,有一个常用的东西就是数值范围。比如,假设你想要生成1和100之间的所有数字。Java 8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:
range和rangeClosed。这两个方法都是第一个参数接受起始值,第二个参数接受结束值。但range是不包含结束值的,而rangeClosed则包含结束值。让我们来看一个例子:
在这里插入图片描述

4.7.3 数值流的应用,勾股数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//        // 生成勾股数
//        Stream<int []> gouguStream = IntStream.rangeClosed(1,100)
//                // 生一个勾股数形成一个流
//                .boxed()
//                .flatMap(a -> IntStream.rangeClosed(a,100).filter(b -> Math.sqrt( a*a + b*b) % 1==0)
//                        .mapToObj(b -> new int[]{a,b, (int) Math.sqrt(a*a + b*b)})
//                );
//        gouguStream.forEach(item -> System.out.println(item[0] + "," + item[1] + "," + item[2]));

        Stream<double []> gouguStream2 = IntStream.rangeClosed(1,100)
                // 生一个勾股数形成一个流
                .boxed()
                .flatMap(a -> IntStream.rangeClosed(a,100)
                        .mapToObj(b -> new double[]{a,b, Math.sqrt(a*a + b*b)})
                        .filter(item -> item[2]  % 1 ==0 )
                );
        gouguStream2.forEach(item -> System.out.println(item[0] + "," + item[1] + "," + item[2]));

4.8 构建流

在这里插入图片描述
在这里插入图片描述

4.8.1 由值创建流

在这里插入图片描述

4.8.2 由数组创建流

在这里插入图片描述

4.8.3 由文件创建流

在这里插入图片描述

4.8.4 由函数生成流:创建无限流

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.java.lamdba.four;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.function.IntSupplier;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StructStreamDemo {
    public static void main(String[] args) {

        // 由值创建流
        Stream<String> stringStream = Stream.of("java8", "lamdba", "adasdasd");
        stringStream.map(String::toUpperCase).forEach(item -> System.out.println(item));
        // 创建空流
        Stream<String> emptyStream = Stream.empty();

        // 数组创建流
        int[] numbers = {2, 3, 5, 7, 11, 13};
        int sum = Arrays.stream(numbers).sum();

        // 由文件生成流
        long uniqueWords = 0;
        try {
            Stream<String> stringStream1 = Files.lines(Paths.get("E:\\learn\\java_learning\\design\\lamdba\\src\\main\\resources\\data.txt"), Charset.defaultCharset());
            uniqueWords = stringStream1.flatMap(line -> Arrays.stream(line.split(" ")))
                    .distinct()
                    .count();
            System.out.println(uniqueWords);
        } catch (Exception ex) {
            System.out.println(ex);
        }

        // c由函数创建无限流,
        // 1.迭代
        Stream.iterate(0, n -> n + 2)
                .limit(10)
                .forEach(System.out::println);

        // 斐波那契数列
//        Stream.iterate(new int[]{0, 1},
//                t -> new int[]{t[1],t[0] + t[1]})
//                .limit(10)
//                .map(t -> t[0])
//                .forEach(System.out::println);

        IntSupplier fib = new IntSupplier(){
            private int previous = 0;
            private int current = 1;
            @Override
            public int getAsInt(){
                int oldPrevious = this.previous;
                int nextValue = this.previous + this.current;
                this.previous = this.current;
                this.current = nextValue;
                return oldPrevious;
            }
        };
        IntStream.generate(fib).limit(10).forEach(System.out::println);
    }
}


4.9 小结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值