拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 十七、JDK8 新特性(完结)

十七、JDK8 新特性(完结)

白鹭 - 2022-02-12 2113 0 0

十七、JDK8 新特性


17.1 Lambda表达式介绍


17.1.1 Lambda表达式案例

先来看案例:

package com.itheima.lambda;

/**
 * @author: Carl Zhang
 * @create: 2021-12-31 14:57
 * 体验Lambda表达式和传统表达式区别
 * 实作游泳
 */
public class Lambda01 {
    public static void main(String[] args) {
        /*
        * 结论:1. 传统的匿名内部类方法解决界面自变量问题,需要 创建匿名内部类物件,实作界面方法,两步 --关注点 怎么做
        *      2. Lambda表达式只需要一条式子,代码简介,关注点更明确在方法功能和输出 -- 关注点 做什么
        *      3. 这种关注方法能做什么的思想就是函式式编程思想
        * */

        //传统方法实作游泳 - 匿名内部类
        swim(new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类的游泳....");
            }
        });

        //Lambda表达式实作
        swim(() -> System.out.println("匿名内部类的游泳...."));
    }

    public static void swim (Swim swim) {
        swim.swimming();
    }
}

interface Swim {
    /**
     * 游泳
     * */
    void swimming();
}

注意:lambda 表达式可以理解为对匿名内部类的一种简化 , 但是本质是有区别的

17.1.2 引入函式式编程思想

介绍:

  • 在数学中,函式就是有输入量、输出量的一套计算方案,也就是“拿资料做操作”
  • lambda 是就是函式式编程思想的一种体现

17.1.3 函式式编程思想和面向物件编程思想的对比

  • 面向物件思想 :
    • 强调的是用物件去完成某些功能 -- 怎么做
  • 函式式编程思想 :
    • 强调的是结果 , 而不是怎么去做 -- 做什么

17.2 函式式界面


17.2.1 函式式界面介绍

  • 概念:

    • 只有一个抽象方法需要重写的界面就是函式式界面,
    • 函式式界面是允许有其他的非抽象方法的存在例如静态方法,默认方法,私有方法,
  • 注解: 为了标识界面是一个函式式界面,可以在界面之上加上一个注解: @FunctionalInterface

  • 相关APIJDK 中的 java.util.function 包里的界面都是函式式界面

我们以前学的 Runnable 界面也是函式式界面
image.png

也可以自定义一个函式式界面:

package com.itheima.lambda;

/**
 * @author CarlZhang
 * 自定义一个函式式界面
 */
@SuppressWarnings("ALL")
@FunctionalInterface
public interface FunctionalInterface01 {
    /**
     * 只有一个 要重写的 抽象方法
     */
    void method01();

    /**
     * 继承Object类的方法
     */
    @Override
    String toString();
    
    /**
     * jdk1.8 界面里可以有静态方法和默认方法
     * */
    static void method02() {
        System.out.println("FunctionalInterface01界面里的静态方法");
    }
    
    /**
     * 默认方法
     * */
    default void method03() {
        System.out.println("FunctionalInterface01界面里的默认方法");
    }
}

@FunctionalInterface
interface FunctionalInterface02 extends FunctionalInterface01{
    //报错:因为此处有两个要重写的抽象法, 一个父类界面的一个此界面的,
    //结论:函式式界面里只能有一个要重写的抽象方法,父类界面里的也算,而Object类比较特殊,
    //      界面里有重写Object类的抽象方法不影响函式式界面的判定

    //void method02();
}

17.2.2 注意事项和使用细节

  • 界面里只能有一个要重写的抽象方法,继承自 **Object** 类的方法除外
  • 可以用注解 @FunctionalInterface 来表示函式式界面

17.3 Lambda表达式的使用


17.3.1 Lambda表达式语法

标准格式(形参串列) - > { //要实作方法的方法体... }

17.3.2 Lambda表达式使用案例

/**
 * @author: Carl Zhang
 * @create: 2021-12-31 16:32
 * 练习1:
 * 1 撰写一个界面(ShowHandler)
 * 2 在该界面中存在一个抽象方法(show),该方法是无自变量无回传值
 * 3 在测验类(ShowHandlerDemo)中存在一个方法(useShowHandler)
 *   方法的的自变量是ShowHandler型别的,在方法内部呼叫了ShowHandler的show方法
 */
public class ShowHandlerDemo {
    public static void useShowHandler(ShowHandler showHandler) {
        showHandler.show();
    }

    public static void main(String[] args) {
        //呼叫useShowHandler方法
        //使用Lambda表达式实作ShowHandler界面作为自变量
        useShowHandler(() -> {
            System.out.println("使用Lambda表达式实作ShowHandler界面作为自变量");
        });
    }

    /*
    * Lambda表达式格式决议
    * 1. () 表示实作的界面里方法的形参串列
    * 2. -> 语法规定,指向要实作的方法内容
    * 3. {} 要实作的方法的方法体
    *
    * 注意:Lambda表达式实作的界面必须是函式式界面
    * */
}

/**
 * @author CarlZhang
 */
@FunctionalInterface
public interface ShowHandler {
    /**
     * 在该界面中存在一个抽象方法(show),该方法是无自变量无回传值
     * */
    void show();
}
/**
 * @author: Carl Zhang
 * @create: 2021-12-31 16:48
 * 需求
 * 1 首先存在一个界面(StringHandler)
 * 2 在该界面中存在一个抽象方法(printMessage),该方法是有自变量无回传值
 * 3 在测验类(StringHandlerDemo)中存在一个方法(useStringHandler),
 *   方法的的自变量是StringHandler型别的,
 *   在方法内部呼叫了StringHandler的printMessage方法
 */
public class StringHandlerDemo {
    public static void useStringHandler(StringHandler stringHandler) {
        stringHandler.printMessage("Hello, World");
    }

    public static void main(String[] args) {
        //使用lambda表达式实作StringHandler, 作为自变量传递
        //结论:
        // 1. () 里的内容对应界面里方法()的内容,是形式自变量,lambda表达式看作一个界面实作类
        // 2. 只有一个自变量情况下,可以省略() 
        useStringHandler(String s -> {
            System.out.println("呼叫Lambda表达式的代码块 " + s);
        });

        //匿名内部类的方式实作
        useStringHandler(new StringHandler() {
            @Override
            public void printMessage(String s) {
                System.out.println("匿名内部类的方法 " + s);
            }
        });
    }
}

@FunctionalInterface
public interface StringHandler {
    /**
     * 在该界面中存在一个抽象方法(printMessage),该方法是有自变量无回传值
     * @param s 任意字符串
     */
    void printMessage(String s);
}
package com.heima.lambda;

import org.omg.CORBA.PUBLIC_MEMBER;

/**
 * @author Carl Zhang
 * @description
 * @date 2022/1/1 20:32
 * 1 首先存在一个界面(Calculator)
 * 2 在该界面中存在一个抽象方法(calc),该方法是有自变量也有回传值
 * 3 在测验类(CalculatorDemo)中存在一个方法(useCalculator)
 * 方法的的自变量是Calculator型别的
 * 在方法内部呼叫了Calculator的calc方法
 */
public class CalculatorDemo {
    public static void useCalculator(Calculator calculator) {
        System.out.println(calculator.calc(11, 12));
    }

    public static void main(String[] args) {
        /*
         * 1. 有参有回传值的方法,直接写(形参串列) -> { return 回传值; },
         *    进一步体现 (输入) - > {输出} 的函式式编程思想
         * 2. 自变量型别可以省略,有多个自变量不能只省略一个
         * 3. 代码块只有一句,则可以省略大括号和分号,甚至return
         * */
        //useCalculator((int num1, int num2) -> {
        //    return num1 + num2;
        //});

        useCalculator((num1, num2) -> num1 + num2);
    }
}

/**
 * @author CarlZhang
 * 1 首先存在一个界面(Calculator)
 * 2 在该界面中存在一个抽象方法(calc),该方法是有自变量也有回传值
 */
@FunctionalInterface
public interface Calculator {
    /**
     * 计算两数之和
     * @param num1 第一个数
     * @param num2 第二个数
     * @return 两数之和
     */
    int calc(int num1, int num2);

}

17.3.2 注意事项和使用细节

使用前提Lambda 表达式实作的界面必须是函式式界面
格式决议

  • Lambda表达式可看做函式式界面的一个实作类物件
  • () 表示实作的界面里方法的形参串列,没有可以空着,
    • 自变量型别可以省略,有多个自变量不能只省略一个
    • 只有一个自变量可以省略 ()
  • -> 语法规定,指向要实作的方法内容
  • {} 要实作的方法的方法体
    • 代码块里只有一句,则可以省略 {};,甚至 return
  • (形参) -> {回传值} 的格式体现了 (输入) -> {输出} 的函式式编程思想

17.4 Lambda表达式和匿名内部类的区别

  • 作用物件不同 :
    • 匿名内部类:可以是界面,也可以是抽象类,还可以是具体类
    • Lambda表达式 :只能是函式式界面
  • 使用场景不同 :
    • 如果界面中有且仅有一个抽象方法,可以使用 Lambda 表达式,也可以使用匿名内部类
    • 如果界面中多于一个抽象方法,只能使用匿名内部类,而不能使用 Lambda 表达式
  • 实作原理不同 :
    • 匿名内部类:编译之后,产生一个单独的 .class 字节码档案
    • Lambda 表达式:编译之后,没有一个单独的 .class 字节码档案,对应的字节码会在运行的时候动态生成
/**
 * @author Carl Zhang
 * @description Lambda表达式和匿名内部类的区别
 * @date 2022/1/1 21:36
 */
public class LambdaVsAnonymous {
    public static void main(String[] args) {
        
        //Lambda表达式呼叫show方法 -- 编译后没有.class档案
        Test test = () -> System.out.println("Hello, World");
        test.show();

        //匿名内部类呼叫show方法 -- 有LambdaVsAnonymous$1.class档案
        new Test() {
            @Override
            public void show() {
                System.out.println("Hello, World");
            }
        }.show();
    }
}

@FunctionalInterface
interface Test {
    /**
     * 打印方法
     */
    void show();
}

17.5 Stream 流


17.5.1 Stream的体验

import java.util.ArrayList;

/**
 * @author Carl Zhang
 * @description 体验Stream流的好处
 * @date 2022/1/2 17:28
 * 需求:按照下面的要求完成集合的创建和遍历
 * <p>
 * 1 创建一个集合,存盘多个字符串元素
 * "张无忌" , "张翠山" , "张三丰" , "谢广坤" , "赵四" , "刘能" , "小沈阳" , "张良"
 * 2 把集合中所有以"张"开头的元素存盘到一个新的集合
 * 3 把"张"开头的集合中的长度为3的元素存盘到一个新的集合
 * 4 遍历上一步得到的集合
 */
public class Stream01 {
    public static void main(String[] args) {
        //集合的方式
        //1.创建集合,添加资料
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张翠山");
        list.add("张三丰");
        list.add("谢广坤");
        list.add("赵四");
        list.add("刘能");
        list.add("小沈阳");
        list.add("张良");

        ArrayList<String> newList = new ArrayList<>();
        ArrayList<String> newList2 = new ArrayList<>();

        //"张"开头的元素添加到新集合
        for (String s : list) {
            if (s.startsWith("张")) {
                //3."张"开头的元素添加到新集合
                newList.add(s);
            }
        }

        //"张"开头的且长度为3的添加到另一个元素
        for (String s : newList) {
            if (s.startsWith("张") && s.length() == 3) {
                newList2.add(s);
            }
        }

        //4.打印
        System.out.println(newList);
        System.out.println(newList2);

        System.out.println("===================");

        //Stream流的方式 获取并列印"张"开头的且长度为3的元素 -- 使对容器里资料的操作进行了简化
        list.stream().filter(s -> s.startsWith("张") && s.length()
                == 3).forEach(s -> System.out.println(s));
    }
}

17.5.2 Stream流介绍

image.png

image.png

17.6 Stream流三类方法


17.6.1 Stream流三类方法介绍

  • 获取 Stream
    • 创建一条流水线,并把资料放到流水线上准备进行操作
  • 中间方法
    • 流水线上的操作,
    • 一次操作完毕之后,还可以继续进行其他操作
  • 终结方法
    • 一个 Stream 流只能有一个终结方法
    • 是流水线上的最后一个操作

17.6.2 Stream流 - 获取方法

  • 单列集合
    • 可以使用Collection 界面中的默认方法 stream() 生成流
    • default Stream<E> stream()
  • 双列集合
    • 双列集合不能直接获取 , 需要间接的生成流
    • 可以先通过 keySet() 或者 entrySet()获取一个 Set 集合,再获取 Stream
  • 阵列
    • Arrays 中的静态方法 stream 生成流
import java.util.*;
import java.util.stream.Stream;

/**
 * @author Carl Zhang
 * @description Stream流的获取方法
 * @date 2022/1/2 17:59
 */
@SuppressWarnings("ALL")
public class StreamGetMethod {
    public static void main(String[] args) {
        //获取单列集合的Stream流
        singleSetStream();

        //获取双列集合的Stream流
        doubleSetStream();

        //获取阵列的Stream流
        arrayStream();

        //获取任意元素的stream流 --了解
        int[] array = {1, 2, 3, 4, 5, 6};
        Stream.of(array).forEach(i -> System.out.println(i)); //[I@7ba4f24f
        Stream.of(1, 2, 3, 4, 5, 6).forEach(i -> System.out.println(i));
    }

    private static void arrayStream() {
        System.out.println("获取阵列的Stream流");
        int[] arr = {1, 2, 3, 4, 5, 6};
        Arrays.stream(arr).forEach(i -> System.out.println(i));
    }

    private static void doubleSetStream() {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("it001", "曹植");
        hashMap.put("it002", "曹丕");
        hashMap.put("it003", "曹熊");
        hashMap.put("it004", "曹冲");
        hashMap.put("it005", "曹昂");

        // 双列集合不能直接获取 , 需要间接的生成流
        // 可以先通过keySet或者entrySet获取一个Set集合,再获取Stream流
        System.out.println("获取双列集合的Stream流");
        Set<Map.Entry<String, String>> entries = hashMap.entrySet();
        entries.stream().forEach(entry -> System.out.println(entry.getKey() +
                "-" + entry.getValue()));
    }

    private static void singleSetStream() {
        ArrayList<String> list = new ArrayList<>();
        list.add("迪丽热巴");
        list.add("古力娜扎");
        list.add("马尔扎哈");
        list.add("欧阳娜娜");

        // 可以使用Collection界面中的默认方法stream()生成流
        // default Stream<E> stream()
        System.out.println("获取单列集合的Stream流");
        list.stream().forEach((String s) -> {
            System.out.println(s);
        });
    }
}

17.6.3 Stream流 - 中间方法

特点:回传了 Stream 流物件,用以继续呼叫方法进行操作流物件

  • Stream<T> filter(Predicate predicate) :用于对流中的资料进行过滤
    • Predicate 界面中的方法 : boolean test(T t) :对给定的自变量进行判断,回传一个布林值
  • Stream<T> limit(long maxSize) :截取指定自变量个数的资料
  • Stream<T> skip(long n) :跳过指定自变量个数的资料
  • static <T> Stream<T> concat(Stream a, Stream b) :合并a和b两个流为一个流
  • Stream<T> distinct() :去除流中重复的元素,依赖(hashCode和equals方法)
  • Stream<T> sorted () : 将流中元素按照自然排序的规则排序
  • Stream<T> sorted (Comparator<? super T> comparator) : 将流中元素按照自定义比较器规则排序
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @author Carl Zhang
 * @description Stream流的中间方法
 * @date 2022/1/2 19:12
 */
@SuppressWarnings("ALL")
public class StreamCentreMethod {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张翠山");
        list.add("张三丰");
        list.add("谢广坤");
        list.add("赵四");
        list.add("刘能");
        list.add("小沈阳");
        list.add("张良");
        list.add("张良");
        list.add("张良");
        list.add(new String("张良"));

        //1 Stream<T> filter(Predicate predicate):用于对流中的资料进行过滤
        //  Predicate函式式界面的方法 : boolean test(T t):对给定的自变量进行判断,回传一个布林值
        //  T 是泛型,Stream流里的元素型别
        //  回传true就留下,false就过滤掉
        //打印集合中三个字名字的元素
        //list.stream().filter(new Predicate<String>() {
        //    @Override
        //    public boolean test(String s) {
        //        return s.length() == 3;
        //    }
        //}).forEach(s -> System.out.println(s));
        list.stream().filter(s -> s.length() == 3).forEach(s -> System.out.println(s));

        //2 Stream<T> limit(long maxSize):截取指定自变量个数的资料
        //获取前两个元素
        Stream<String> stream = list.stream();
        stream.limit(2).forEach(s -> System.out.println(s));

        //3 Stream<T> skip(long n):跳过指定自变量个数的资料
        //跳过前两个元素,打印后面的元素
        //例外IllegalStateException:stream has already been operated upon or closed
        //stream.skip(2).forEach(s -> System.out.println(s));
        list.stream().skip(2).forEach(s -> System.out.println(s));

        //4 static <T> Stream<T> concat(Stream a, Stream b):合并a和b两个流为一个流
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("迪丽热巴");
        list2.add("古力娜扎");
        list2.add("欧阳娜娜");
        list2.add("马尔扎哈");
        Stream.concat(list.stream(), list2.stream()).forEach(s -> System.out.println(s));

        //5 Stream<T> distinct():去除流中重复的元素,依赖(hashCode()和equals())
        list.stream().distinct().forEach(s -> System.out.println(s));
        //这里只剩一个"张良",因为String里的方法根据value的值来回传hashCode
        //new String("张良").hashCode();

        //6 Stream<T> sorted () : 将流中元素按照自然排序的规则排序
        list.stream().sorted().forEach(s -> System.out.println(s));

        //7 Stream<T> sorted (Comparator<? super T> comparator) : 将流中元素按照自定义比较器规则排序
        list.stream().sorted(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.length() - o1.length();
            }
        }).forEach(s -> System.out.println(s));
        System.out.println();
        list.stream().sorted((s1, s2) -> s2.length() - s1.length()).forEach(
                s -> System.out.println(s)
        );
    }
}

17.6.4 Stream流 - 终结方法

特点:慷训传值,不能继续呼叫方法进行操作流物件

  • void forEach(Consumer action) :对此流的每个元素执行操作
    • Consumer 界面中的方法 void accept(T t) :对给定的自变量执行此操作
  • long count() :回传此流中的元素数
import java.util.ArrayList;
import java.util.function.Consumer;

/**
 * @author Carl Zhang
 * @description Stream流的终结方法
 * @date 2022/1/2 19:48
 */
public class StreamEndMethod {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张翠山");
        list.add("张三丰");
        list.add("谢广坤");

        //1 void forEach(Consumer action):对此流的每个元素执行操作
        //  Consumer界面中的方法 void accept(T t):对给定的自变量执行此操作
        // 把list集合中的元素放在stream流中
        // forEach方法会回圈遍历流中的资料
        // 并回圈呼叫accept方法 , 把资料传给s
        // 所以s就代表的是流中的每一个资料
        // 我们只要在accept方法中对资料做业务逻辑处理即可
        list.stream().forEach(s -> System.out.println(s));

        //2. long count():回传此流中的元素数
        //结果:4
        System.out.println(list.stream().count());
    }
}

17.7 Stream流的收集方法


17.7.1 使用收集方法的原因

问题:使用 Stream 流的方式操作完毕之后,我想把流中的资料起来,该怎么办呢?

引出收集方法

package com.heima.stream;

import java.util.ArrayList;

/**
 * @author Carl Zhang
 * @description 使用收集方法的原因
 * @date 2022/1/2 20:04
 * 需求:过滤元素并遍历集合
 * 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
 * 将集合中的奇数洗掉,只保留偶数,
 * 遍历集合得到2,4,6,8,10
 */
public class CollectionMethod01 {
    public static void main(String[] args) {
        //JDK9 新特性 直接传入一个不可变集合的元素,来创建新集合
        //ArrayList<Integer> list = new ArrayList<>(List.of(1,2,3,4,5,6,7,8,9,10));
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }

        //使用Stream流过滤掉集合中的奇数,获取偶数
        list.stream().filter(i -> i % 2 == 0).forEach(i -> System.out.println(i));

        //结论:list集合里的数未改变
        //如果需要保留流里面过滤后的元素 -> 使用收集方法
        System.out.println(list);
    }
}

17.7.2 收集方法介绍

Stream 流的收集方法
R collect(Collector collector) : 此方法只负责收集流中的资料 , 创建集合添加资料动作需要依赖于自变量

收集方法也可以看作一种终结方法,呼叫完 collect() 不回传 Stream 物件,不可再对流进行操作

17.7.2 三种收集方式

工具类 Collectors 提供了具体的收集方式

public static <T> Collector toList() :把元素收集到List集合中

public static <T> Collector toSet() :把元素收集到Set集合中

package com.heima.stream;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * @author Carl Zhang
 * @description Stream流的收集方法
 * @date 2022/1/2 20:22
 * 需求 :
 * 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
 * 将集合中的奇数洗掉,只保留偶数,
 * 遍历集合得到2,4,6,8,10
 */
public class CollectionMethod02 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }

        //通过收集方法获取过滤后的元素
        //决议:
        //1. R collect(Collector collector) : 此方法只负责收集流中的资料 , 创建集合添加资料动作需要依赖于自变量
        //2. 通过工具类Collector里的规则来将收集到的元素保存到集合里
        //   public static <T> Collector toList():把元素收集到List集合中
        List<Integer> list1 = list.stream().filter(i -> i % 2 == 0).collect(
                Collectors.toList());
        System.out.println(list1); //[2, 4, 6, 8, 10]

        //将过滤好的元素收集到Set集合里
        //public static <T> Collector toSet():把元素收集到Set集合中
        Set<Integer> set = list.stream().filter(i -> i % 2 == 0).collect(
                Collectors.toSet()
        );
        System.out.println(set); //[2, 4, 6, 8, 10]
    }
}

public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中

import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Carl Zhang
 * @description 将过滤好的元素收集到Map集合里
 * @date 2022/1/2 20:33
 * public static  Collector toMap(Function keyMapper,Function valueMapper):
 * 把元素收集到Map集合中
 * <p>
 * 1 创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄
 * "zhangsan,23"
 * "lisi,24"
 * "wangwu,25"
 * 2 保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
 */
public class CollectionMethod03 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("zhangsan,23");
        list.add("lisi,24");
        list.add("wangwu,25");

        //筛选出24岁以上的元素
        Stream<String> stream = list.stream().filter(s -> {
            String[] split = s.split(",");
            //获取年龄
            int age = Integer.parseInt(split[1]);
            //筛选出大于等于24岁的
            return age >= 24;
        });

        //将过滤好的元素收集到Map集合
        //public static  Collector toMap(Function keyMapper,Function valueMapper):
        Map<String, String> collect = stream.collect(Collectors.toMap(
                // 获取键:Function keyMapper -- 传入一个函式式界面的实作类
                // s 表示流里的元素
                // 获取第一个元素,做为键
                s -> s.split(",")[0],
                // 获取值Function valueMapper)
                s -> s.split(",")[1]
        ));

        //遍历
        Set<Map.Entry<String, String>> entries = collect.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey() + "-" + entry.getValue());
        }
    }
}
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *