jdk8 lambda学习

1、函数式接口与lambda表达式

概述:

  函数式接口也是 java interface 的一种,但还需要满足:

  一个函数式接口只有一个抽象方法(SAM,single abstract method);
  Object 类中的 public abstract method 不会被视为单一的抽象方法;
  函数式接口可以有默认方法和静态方法;
  函数式接口可以用@FunctionalInterface 注解进行修饰。

常用函数式接口分类:

  supplier:供给型,无参有返回值

@FunctionalInterface
interface Test3{
    String printHello();
}

  consumer:消费型,有参,无返回值

@FunctionalInterface
interface Test{
    void test(String str);
}

  predicate:断言型接口,有参,返回boolean

@FunctionalInterface
interface Test2{
    boolean compare(int a, int b);
}

  function:函数式接口,有参,有返回值

@FunctionalInterface
interface Test1{
    int add(int a, int b);
}

 

lambda语法格式:

    (parameters) -> expression

    或 (parameters) ->{ statements; }

lambda表达式语法特征:

  1、可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  2、可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  3、可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  4、可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

转换示例:

  lambda表达式根据参数类型确定接口类型,接口要求为函数式接口,只需要关注接口方法实现,可以省略创建接口对象代码,lambda表达式本质上是得到接口对象

Test test0 = new Test() {
            @Override
            public void test(String str) {
                System.out.println(str);
            }
        };
        
Test test = (str) -> System.out.println(str);
 Test1 test1 = (a, b) -> a+b;
 System.out.println(test1.add(3, 7));

 Test2 test2 = (a, b) -> a>b;
 System.out.println(test2.compare(3, 7));

 Test3 test3 = () -> "你好";
 System.out.println(test3.printHello());

 

2、方法引用:

  实例方法引用:

    默认的,我们引用实例方法使用的是对象名.方法名语法,实例方法引用可以使用类名::方法名的语法

  静态方法引用:

    默认的,我们引用静态方法使用类名.方法名,静态方法引用可以使用类名::方法名的语法

  构造方法引用:

    默认的,我们使用new 类名(参数列表)调用,构造方法信用可以使用类名::new的语法

  数组构造引用:

    默认使用new 数据类型[长度]创建,数组构造引用可以使用数据类型[]::new的语法

public class Test06 {
    public static void main(String[] args) {
        //构造引用
        Car car = Car.create(Car::new);

        //变成数组方便使用lambda
        List<Car> cars = Arrays.asList(car);

        //实例方法引用
        cars.forEach(Car::repair);

        //静态方法引用
        cars.forEach(Car::collide);

        //数组引用
        Function<Integer, Car[]> arrCreate = Car[]::new;
        Car[] carArr = arrCreate.apply(3);

    }
}

class Car {
    public static Car create(final Supplier<Car> supplier) {
        return supplier.get();
    }

    public static void collide(final Car car) {
        System.out.println("Collided " + car.toString());
    }

    public void follow(final Car another) {
        System.out.println("Following the " + another.toString());
    }

    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
}

 

3、内部迭代与外部迭代

 外部迭代是由用户自己在客户端中写的循环代码, 内部迭代是由Jdk在库中执行的循环代码, 即循环写的位置从外部转移到了jdk内部.
两种迭代方式速率差别不大,内部迭代优势:
用户只需要关注问题,无需关注如何解决问题的细节。
使得 JVM可以利用短路、并行等对性能的提升变成可能
     final long count = 100000000;
        List<Long> list = new ArrayList<>();
        for (long i = 0; i < count; i++) {
            list.add(i);
        }

        //=========传统方式进行外部迭代=========
        Instant begin = Instant.now();
        for (Long i : list) {
            System.out.print("");
        }
        System.out.println("--------------------------");
        Instant end = Instant.now();
        System.out.println("传统方式进行外部迭代" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());

        //=========jdk8 Collection.forEach(...)进行内部迭代========
        begin = Instant.now();
        list.forEach(i -> System.out.print(""));
        System.out.println("--------------------------");
        end = Instant.now();
        System.out.println("jdk8 Collection.forEach方式进行内部迭代" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());

        //=========jdk8 stream进行内部迭代========
        begin = Instant.now();
        list.stream().forEach(i -> System.out.print(""));
        System.out.println("--------------------------");
        end = Instant.now();
        System.out.println("jdk8 Stream方式进行内部迭代" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());

        //=========jdk8 parallelStream进行内部迭代========
        begin = Instant.now();
        list.parallelStream().forEach(i -> System.out.print(""));
        System.out.println("--------------------------");
        end = Instant.now();
        System.out.println("jdk8 parallelStream方式进行内部迭代" + count + "次,耗时(ms):" + Duration.between(begin, end).toMillis());

 

4、Stream的常用方法:

  (1)、获得stream流:

      //已知,可以通过集合框架.stream方法构建
        Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream();

        //可以使用Stream.of方法,将对象,对象参数列表转变成为流对象
        Stream<Integer> integerStream = Stream.of(1, 2, 3);
        Stream<String> str = Stream.of("str");

        //stream对象的.parallel()方法可以得到对应并行流
        Stream<Integer> parallelStream = Stream.of(1, 2, 3).parallel();

        //empty方法创建一个空流
        Stream<Object> empty = Stream.empty();

    并行流与串行流的区别在于并行流可以多线程处理,加快速率

 

  (2)、forEach遍历

Arrays.asList(1, 2, 3).stream().forEach(obj -> System.out.print(obj + " "));

 

  (3)、filter 流内数据筛选

    //筛选出0~9当中>5的数
        Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream();
        stream.filter(i -> i > 5).forEach(i -> System.out.print(i + " "));

 

  (4)、map 流内数据转换为其他类型

     Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream();
        stream
                .filter(i -> i > 5)
                .map(i -> {
                    switch (i) {
                        case 1:
                            return "一";
                        case 2:
                            return "二";
                        case 3:
                            return "三";
                        case 4:
                            return "四";
                        case 5:
                            return "五";
                        case 6:
                            return "六";
                        case 7:
                            return "七";
                        case 8:
                            return "八";
                        case 9:
                            return "九";
                    }
                    return "未知";
                }).forEach(d -> System.out.print(d + " "));

        //map进行限制的其他接口:mapToInt()、mapToLong()、mapToDouble()

 

  (5)、flatMap 流内数据转换为流再合并到到同一个流中,返回的是stream对象

     //演示1对多
        Arrays.asList("hello", "world").stream().map(str -> str.split("")).forEach(obj -> System.out.println(Arrays.toString(obj)));

        Arrays.asList("hello", "world").stream().flatMap(str -> Arrays.stream(str.split(""))).forEach(obj -> System.out.print(obj + " "));

        //flatMapToLong、flatMapToDouble等就不多赘余描述了

  (6)、distinct 去重, sorted 排序

     List<Integer> integers = Arrays.asList(1, 1, 3, 5, 2, 6, 6);
        integers.stream()
                .distinct()
                .sorted()
                .forEach(i -> System.out.print(i + " "));
        //自定义排序规则
        System.out.println();
        integers.stream()
                .distinct()
                .sorted((Integer o1, Integer o2) ->
                        o1 < o2 ? 1 : (o1.equals(o2)) ? 0 : -1)
                .forEach(i -> System.out.print(i + " "));

 

  (7)、skip跳过, limit截取 控制流内指针的方法

    //使用skip + limit实现了类似分页的效果
        int pageSize = 2;
        int pageNumber = 2;

        List<String> collect = Stream.of("a", "b", "c", "d", "e", "f")
                .skip(pageSize * (pageNumber - 1))
                .limit(pageSize)
                .collect(Collectors.toList());

        for (String str : collect) {
            System.out.println(str);
        }

 

  (8)、获取值与匹配:findFirst、findAny、anyMatch、allMatch

    /**
     * findFirst() 得到第一个元素
     * findAny() 得到随机一个元素。这个一般是在并行流查找的使用使用。串行和findFirst没区别
     * anyMatch() 任意匹配
     * allMatch() 全部匹配
     */
    @Test
    public void testOther(){
        System.out.println(Stream.of("a", "ab", "ccc").findFirst().get());
        System.out.println(Stream.of("a", "ab", "ccc").findAny().get());

        //想要将元素倒叙使用的是sort方法,指定好排序规则即可

        boolean x = Stream.of("a", "ab", "ccc").anyMatch(str -> str.contains("c"));
        System.out.println("容器内有包含c字符的字符串?" + x);

        boolean b = Stream.of("a", "ab", "ccc").allMatch(str -> str.contains("c"));
        System.out.println("容器内字符串全部包含c字符?" + b);

    }

  (9)、统计操作min、max、count、reduce(自定义统计策略)

/**
     * 聚合操作:
     *  min、max、reduce
     */
    @Test
    public void testPolymerization(){
        int max = Stream.of(1, 3, 5, 7, 9)
                .max(Comparator.naturalOrder()).get();
        System.out.println(max);

        int min = Stream.of(1, 3, 5, 7, 9)
                .min(Comparator.naturalOrder()).get();
        System.out.println(min);

        long count = Stream.of(1, 3, 5, 7, 9)
                .filter(number -> number > 3)
                .count();
        System.out.println("大于三的数量有:" + count);


        //如果我们想要类似sum操作,怎么办呢?使用reduce方法达到想要的效果
        Integer sum = Stream.of(1, 3, 5, 7, 9).reduce((a, b) -> a + b).get();
        System.out.println("1 + 3 + 5 + 7 + 9 =" + sum);

        Integer sum1 = Stream.of(1, 2, 3, 4, 5).reduce(100, (a, b) -> a + b);
        System.out.println("100 + 1 + 2 + 3 + 4 + 5 = " + sum1);

        //前面两个reduce区别在于第二个可以设置初始值,但是都要求聚合产生的数据类型不能发生变化。reduce一次操作的结果作为上一次操作的参数
        //reduce的第三种方法可以支持聚合产生的结果为其他类型,非元素内容类型
        //例如,使用reduce方式3实现count操作
        Integer count1 = Stream.of("a", "bc", "ca", "d", "abc")
                .filter(str -> str.length() > 1)
                .reduce(0, (identity, ele) -> identity + 1, (identity, ele) -> null);
        System.out.println("字符串列表中长度>1的字符串个数为:" + count1);

        //第三个参数是指的在并行流的情况下,各个线程得到的结果的合并方式,前面写为null是因为不是并行流它并不会生效
        Integer count2 = Stream.of("a", "bc", "ca", "d", "abc")
                .parallel()
                .filter(str -> str.length() > 1)
                .reduce(0, (identity, ele) -> identity + 1, (identity, ele) -> identity + ele);
        System.out.println("并行流得到的字符串列表中长度>1的字符串个数为:" + count2);

    }

 

  (10)、static concat 流的合并

    /**
     * static concat 合并,类似mysql中的字符串合并,这里是流的合并
     */
    @Test
    public void testConcat() {
        Stream.concat(Stream.of(1, 2, 3), Stream.of("a", "b", "c")).forEach(obj -> System.out.print(obj + " "));
    }

 

  (11)、peek:lambda表达式提供的debug

    /**
     * peek方法:stream提供的一个方便调试的方法,可以在peek代码块内进行打印中间结果
     * 注意,peek方法一定要对流对象进行了操作才会触发,我们的例子使用了collect操作触发
     * 该方法主要用于调试,方便debug查看Stream内进行处理的每个元素。
     *
     * idea目前有插件可以支持直接debug在stream过程函数中
     */
    @Test
    public void testPeek(){
        Stream.of("a", "ab", "abc", "abcd")
                .filter(str -> str.length() > 2)
                .peek(str -> System.out.println("经过过滤的数据:" + str))
                .map(str -> str.toUpperCase())
                .peek(str -> System.out.println("处理之后的数据:" + str))
                .collect(Collectors.toList());

    }

 

  (12)、collect 数据收集,将数据从流变为普通java对象等

    @Test
    /** collect 数据收集,将流内数据提取出来 */
    public void testCollect() {
        Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream();
        List<Integer> integerList = stream
                .filter(i -> i > 5)
                .collect(Collectors.toList());
        integerList.forEach(i -> System.out.print(i + " "));

        //系统提供的收集器:Collectors.toList()、 Collectors.toSet()....
    }

 

 5、Collector收集器学习

收集器Collector 将stream流中元素迭代操作变成最终形式

收集动作与执行步骤组成

 1、supplier() 创建接受容器

2、accumulator() 将新元素加入容器
3、combiner() 合并两个结果容器(并行流使用,将多个线程产生的结果容器合并)
4、finisher() 转换到最终形态的操作

属性:
Set<> characteristics
特征集合:
Collector.Characteristics 枚举对象类型
CONCURRENT 并发的
UNORDERED 无序的
IDENTITY_FINISH 表示中间结果容器类型与最终结果类型一致。设置此特性时finiser()方法不会被调用

自定义收集器:
of方法:
  static <T,R> Collector<T,R,R> of(Supplier<R>
supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics)
  static <T,A,R> Collector<T,A,R> of(Supplier<A> supplier, BiConsumer<A,T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher, Collector.Characteristics... characteristics)

收集器工具类:Collectors
内置收集方法:
toList() 将流内数据转换为List对象

 

    /**
     * 自定义获取toList收集器。 这里定义为方法的原因是方便对于不同的类型T进行复用
     * @param <T>
     * @return
     */
    public static <T> Collector<T, ?, List<T>> toList() {
        return Collector.of(
                () -> new ArrayList<>(),
                (ts, t) -> ts.add(t),
                (list, list2) -> {
                    list.addAll(list2);
                    return list;
                },
                new Collector.Characteristics[0]);
    }

    @Test
    public void test01() {
        //Collectors的toList收集器
        List<String> collect = Stream.of("q", "w", "e", "r").collect(Collectors.toList());

        //自定义收集器达到toList效果
        List<String> collect1 = Stream.of("q", "w", "e", "r").collect(toList());
        for (String str : collect1) {
            System.out.print(str + " ");
        }


    }

 

 6、Collectors收集器工具类学习

  (1)、收集为集合。toCollection、toList、toSet、toMap、toCurrentMap

/**
     * Collectors的提供常见收集器使用:
     *  toCollection()
     *  toList()
     *  toSet()
     *  toMap(keyFunction, valueFunction)
     *  toMap(keyFunction, valueFunction, keySameValueCombineFunction) 最后一个方法是当key相同的时候,value的合并的function
     *  toMap(keyFunction, valueFunction, keySameValueCombineFunction, Supplier) 最后一个方法是指定map容器的创建方式
     *  toConcurrentMap 收集过程并行操作,不做过多赘余说明
     */
    @Test
    public void test02(){
        Set<String> collect = Stream.of("a", "b", "c").collect(Collectors.toSet());
        List<String> collect2 = Stream.of("a", "b", "c").collect(Collectors.toList());
        TreeSet<String> collect1 = Stream.of("a", "b", "c").collect(Collectors.toCollection(() -> new TreeSet<>()));

        //得到数据是否为大写的map
        Map<String, Boolean> collect3 = Stream.of("a", "b", "c").collect(Collectors.toMap(str -> str, str -> str.equals(str.toUpperCase()) ? true : false));
        //统计元素出现的次数
        Map<String, Integer> collect4 = Stream.of("a", "b", "c", "b").collect(Collectors.toMap(
                str -> str,
                str -> 1,
                (valueMapper, value) -> valueMapper.intValue() + 1));
        TreeMap<String, Integer> collect5 = Stream.of("a", "b", "c", "b").collect(Collectors.toMap(
                str -> str,
                str -> 1,
                (valueMapper, value) -> valueMapper.intValue() + 1, TreeMap::new));
        System.out.println(collect);
        System.out.println(collect1);
        System.out.println(collect2);
        System.out.println(collect3);
        System.out.println(collect4);
        System.out.println(collect5);

    }

 

  (2)、join 字符流内容收集方式为连接

    /**
     * join 聚合连接
     */
    @Test
    public void test03(){
        //无任何介质连接,得到结果abc
        String collect = Stream.of("a", "b", "c").collect(Collectors.joining());

        //连接符号为, 得到a,b,c
        String collect1 = Stream.of("a", "b", "c").collect(Collectors.joining(","));

        //连接符号为:, 前缀为:{ 后缀为:}
        String collect2 = Stream.of("a", "b", "c").collect(Collectors.joining(",", "{", "}"));

        System.out.println(collect);
        System.out.println(collect1);
        System.out.println(collect2);
    }

  (3)、mapping:处理数据然后收集    collectingAndThen:针对原来的收集器增加后置处理动作

   /**
     * mapping  处理数据然后收集,相当于先mapping操作然后收集
     * collectingAndThen 针对原来的收集器,增加新的后置收集处理动作
     */
    @Test
    public void test04(){
        //转大写再收集
        List<String> collect = Stream.of("a", "b", "c").collect(Collectors.mapping((a) -> a.toUpperCase(), Collectors.toList()));
        for (String str : collect) {
            System.out.print(str + " ");
        }

        //在转为list的基础上进行求总数。也就是说收集器的作用就是计算元素个数
        Integer collect1 = Stream.of("a", "b", "c").collect(Collectors.collectingAndThen(Collectors.toList(), list -> list.size()));
    }

  (4)、聚合操作:counting、minBy、maxBy、avragingInt、summingLong等

    /**
     * 聚合操作
     * counting 求总数
     * minBy 最小值
     * maxBy 最大值
     *
     * averagingInt int类型求平均值
     * averagingLong Long类型求平均值
     * averagingDouble Double类型求平均值
     *
     * summingLong 获得Long类型的SummaryStatistics数据
     * summingInt 获得Int类型的SummaryStatistics数据
     * summingDouble 获得Double类型的SummaryStatistics数据
     * SummaryStatistics 数据可以取得以下数据:  getCount()、getSum()、getMin()、getAverage()、getMax()
     */
    @Test
    public void test05() {
        Long count = Stream.of("a", "b", "c").collect(Collectors.counting());

        String min = Stream.of("1", "2", "3").collect(Collectors.minBy(Comparator.naturalOrder())).get();
        String max = Stream.of("1", "2", "3").collect(Collectors.maxBy(Comparator.naturalOrder())).get();
        Double avg = Stream.of(1, 2, 3).collect(Collectors.averagingInt(i -> Integer.valueOf(i)));
        System.out.println("count=" + count);
        System.out.println("min=" + min);
        System.out.println("max=" + max);
        System.out.println("avg=" + avg);

        //SummaryStatistics 数据可以取得以下数据:  getCount()、getSum()、getMin()、getAverage()、getMax()
        DoubleSummaryStatistics collect = Stream.of(1, 2, 3).collect(Collectors.summarizingDouble(obj -> (double) obj));
        System.out.println("最大值:" + collect.getMax() + ", 最小值:" + collect.getMin());
    }

  (5)、reduce 自定义收集实现累加等

 /**
     * 抱歉,自己之前弄明白又记不起来了
     * reduce 做聚合操作,得到单个元素
     * reduce(function ) 传递一个聚合方法,默认将聚合的结果作为第一个参数与第二个参数开始聚合
     * reduce( identity, function) 带了一个参与聚合的初始值
     * reduce( identity, mapper, op) mapper指的是将新元素展缓为identity类型的方法,op指的是元素合并的方法
     */
    @Test
    public void test06() {
        int count = Stream.of(1, 2, 3).collect(Collectors.reducing((a, b) -> a + b)).get();
        Integer collect = Stream.of(1, 2, 3).collect(Collectors.reducing(100, (a, b) -> a + b));

        ArrayList<Integer> list = new ArrayList<>();
        ArrayList<Integer> collect1 = Stream.of(1, 2, 3).collect(Collectors.reducing(
                list,
                (i) -> {
                    ArrayList<Integer> al = new ArrayList<>();
                    al.add(i);
                    return al;
                },
                (ArrayList<Integer> list1, ArrayList<Integer> list2) -> {
                    list1.addAll(list2);
                    return list1;
                }));

        for (Integer i : collect1) {
            System.out.println(i);
        }
    }

  (6)、groupingBy流内元素分组收集

    /**
     * 测试groupingBy
     * Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,   获得key的方法
     * Supplier<M> mapFactory,                    初始化map的方法
     * Collector<? super T, A, D> downstream)     结果收集器
     * <p>
     * Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,   初始化map的方法抵用hashMap的new方法
     * Collector<? super T, A, D> downstream)
     * <p>
     * groupingBy(Function<? super T, ? extends K> classifier)  默认的结果收集器是toList()
     * <p>
     * groupingByConcurrent  并行流分组
     */
    @Test
    public void test07() {
        @Data
        class Box {
            private int width;
            private int height;
            private String name;

            public Box(int width, int height, String name) {
                this.width = width;
                this.height = height;
                this.name = name;
            }
        }

        List<Box> boxList = new ArrayList<>();
        boxList.add(new Box(2, 3, "盒子1"));
        boxList.add(new Box(2, 4, "盒子2"));
        boxList.add(new Box(2, 5, "盒子3"));
        boxList.add(new Box(3, 3, "盒子4"));
        boxList.add(new Box(3, 5, "盒子6"));
        boxList.add(new Box(5, 3, "盒子7"));

        //将盒子根据宽度进行分装,得到map
        Map<Integer, List<Box>> collect = boxList.stream().collect(Collectors.groupingBy(o -> o.getWidth()));

        Map<Integer, List<Box>> list1 = new HashMap<>();
        list1.put(2, new ArrayList<Box>() {{
            add(new Box(2, 3, "盒子10"));
        }});

        //指定获得初始容器的方法
        Map<Integer, List<Box>> collect1 = boxList.stream().collect(Collectors.groupingBy(o -> o.getWidth(),
                () -> list1, Collectors.toList()));


        //分组求总数,类似 select count(*) from dual group by width
        Map<Integer, Long> collect2 = boxList.stream().collect(Collectors.groupingBy(o -> o.getWidth(), Collectors.counting()));

        System.out.println(1);

        //多条件分组,就是收集器为其他的分组收集器

    }

  (7)、partitioningBy  简单分组,分为满足要求与不满足要求的两组

    /**
     * 分组,不过分为true组和false组,相对groupingBy范围小一些
     * partitioningBy(Predicate<? super T> predicate,     判断函数
     * Collector<? super T, A, D> downstream)    收集器
     * <p>
     * partitioningBy(Predicate<? super T> predicate)   使用默认的toList收集器
     */
    @Test
    public void test08() {
        //得到奇偶集合
        Map<Boolean, List<Integer>> collect = Stream.of(1, 2, 3).collect(Collectors.partitioningBy(i -> i % 2 == 0));

        //得到奇偶分别个数
        Map<Boolean, Long> collect1 = Stream.of(1, 2, 3).collect(Collectors.partitioningBy(i -> i % 2 == 0, Collectors.counting()));

        System.out.println(1);
    }

 

7、lambda简单练习

package com.zhen.orc.jdk8;

import lombok.Data;
import org.junit.Test;

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

/**
 * 网上随意找一些练习题刷一下
 *
 * @author zhen
 */
public class Test05 {

    @Test
    public void test01() {
        //有如下7个元素黄药师,冯蘅,郭靖,黄蓉,郭芙,郭襄,郭破虏,使用Stream将以郭字开头的元素存入新数组
        Stream.of("黄药师", "冯蘅", "郭靖", "黄蓉", "郭芙", "郭襄", "郭破虏").filter(str -> str.startsWith("郭")).collect(Collectors.toList()).toArray();
    }

    @Test
    public void test02() {
        //已知ArrayList集合中有如下元素{陈玄风、梅超风、陆乘风、曲灵风、武眠风、冯默风、罗玉风},使用Stream
        //1、取出前2个元素并在控制台打印输出。
        //2、取出后2个元素并在控制台打印输出。
        ArrayList al = new ArrayList();
        al.add("陈玄风");
        al.add("梅超风");
        al.add("陆乘风");
        al.add("曲灵风");
        al.add("武眠风");
        al.add("冯默风");
        al.add("罗玉风");
        System.out.print("前两个元素为:");
        al.stream().limit(2).forEach(str -> System.out.print(str + " "));

        System.out.println();
        System.out.print("后两个元素为:");
        al.stream().sorted((str1, str2) -> -1).limit(2).forEach(str -> System.out.print(str + " "));

    }

    @Test
    public void test03() {
        //有如下整数1,-2,-3,4,-5
        //使用Stream取元素绝对值并打印
        Stream.of(1, -2, -3, 4, -5).map(i -> Math.abs(i)).forEach(i -> System.out.print(i + " "));
    }

    @Test
    public void test04() {
        //给定一个数字列表,如何返回一个由每个数的平方构成的列表呢?
        //比如给定【1,2,3,4,5】, 应该返回【1,4,9,16,25】
        List<Integer> collect = Stream.of(1, 2, 3, 4, 5).map(i -> (int) Math.pow(i, 2)).collect(Collectors.toList());
        System.out.println(collect);
    }

    @Test
    public void test05() {
        //有两个集合,一个有6个男演员,一个有6个女演员,完成下面的功能
        //男演员只要名字为3个字的前三人
        //女演员只要姓林的,并且不要第一个
        //把过滤后的男演员姓名和女演员姓名合并到一起
        //把上一步操作后的元素作为构造方法的参数创建演员对象(实例化一个Actor类,此处尝试使用map),遍历数组

        //1、初始化集合
        ArrayList<String> manArray = new ArrayList<>();
        manArray.add("刘德华");
        manArray.add("成龙");
        manArray.add("吴彦祖");
        manArray.add("周润发");
        manArray.add("周星驰");
        manArray.add("吴京");

        ArrayList<String> womanList = new ArrayList<>();
        womanList.add("林心如");
        womanList.add("孙俪");
        womanList.add("柳岩");
        womanList.add("林青霞");
        womanList.add("王祖贤");
        womanList.add("张曼玉");

        @Data
        class Actor {
            private String name;

            public Actor(String name) {
                this.name = name;
            }

            @Override
            public String toString() {
                return "Actor{" +
                        "name='" + name + '\'' +
                        '}';
            }
        }

        Stream.concat( //合并
                //男演员
                manArray.stream()
                        //名字为3个的
                        .filter(str -> str.length() == 3)
                        //前3人
                        .limit(3),
                //女演员
                womanList.stream()
                        //只要姓林的
                        .filter(str -> str.startsWith("林"))
                        //不要第1个
                        .skip(1))
                //转化为对象
                .map(str -> new Actor(str))
                //遍历对象
                .forEach(actor -> System.out.println(actor));

    }

    @Test
    public void test06() {
        /*
        (1) 找出2011年发生的所有交易,并按交易额排序(从低到高)。
        (2) 交易员都在哪些不同的城市工作过?
        (3) 查找所有来自于剑桥的交易员,并按姓名排序。
        (4) 返回所有交易员的姓名字符串,按字母顺序排序。
        (5) 有没有交易员是在米兰工作的?
        (6) 打印生活在剑桥的交易员的所有交易额。
        (7) 所有交易中,最高的交易额是多少?
        (8) 找到交易额最小的交易。
         */

        //交易类
        @Data
        class Trader {
            private final String name;
            private final String city;

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

        }

        //交易记录类
        @Data
        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;
            }
        }

        //初始数据
        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(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(brian, 2011, 300),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );

        //1、找出2011年发生的所有交易,并按交易额排序(从低到高)。
        transactions.stream().filter(transaction -> transaction.getYear() == 2011).sorted((transactions1, transactions2) -> transactions1.getValue()> transactions2.getValue() ? 1 : (transactions1.getValue() == transactions2.getValue() ? 0 : -1)).forEach(transaction -> System.out.println(transaction));

        //2、交易员都在哪些不同的城市工作过?
        Map<String, HashSet<String>> collect = transactions.stream()
                .collect(
                        Collectors.groupingBy(transaction -> transaction.getTrader().getName(),
                                Collector.of(
                                        () -> new HashSet<>(),
                                        (set, item) -> set.add(item.getTrader().getCity()),
                                        (set1, set2) -> {
                                            set1.addAll(set2);
                                            return set1;
                                        },
                                        new Collector.Characteristics[0])));

        collect.entrySet().stream().forEach(
                entry -> {
                    System.out.print(entry.getKey() + "工作过的城市:");
                    entry.getValue().stream().forEach(str -> System.out.print(str + " "));
                    System.out.println();
                }
        );

        //3、查找所有来自于剑桥的交易员,并按姓名排序。
        System.out.print("来自剑桥的交易员有:");
        transactions.stream()
                .filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
                .map(transaction -> transaction.getTrader())
                .distinct()
                .sorted(Comparator.comparing(Trader::getName)).forEach(trader -> {
            System.out.print(trader.getName() + " ");
        });
        System.out.println();

        //4、返回所有交易员的姓名字符串,按字母顺序排序。
        System.out.print("所有交易员的姓名(字母排序):");
        transactions.stream().map(transaction -> transaction.getTrader().getName()).distinct().sorted(Comparator.naturalOrder()).forEach(str -> {
            System.out.print(str + " ");
        });
        System.out.println();

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

        //6、打印生活在剑桥的交易员的所有交易额
        Long cambridgeTraderMoney = transactions.stream()
                .filter(transaction -> transaction.getTrader().getCity().equals("Cambridge"))
                .map(transaction -> transaction.getValue()).collect(Collectors.counting());

        //7、 所有交易中,最高的交易额是多少?
        int maxTraderValue = transactions.stream().collect(Collectors.maxBy(Comparator.comparing(transaction -> transaction.getValue()))).get().getValue();

        //8、找到交易额最小的交易
        Transaction transaction1 = transactions.stream().collect(Collectors.minBy(Comparator.comparing(transaction -> transaction.getValue()))).get();
    }
}

 

posted @ 2021-04-20 11:40  guodaxia  阅读(116)  评论(0编辑  收藏  举报