1、Stream.map
其作用接收一个泛型T,返回泛型R,map函数的定义,返回的流,表示的泛型是R对象,这个表示,调用这个函数后,可以改变返回的类型。
map方法的源码如下:

/**
     *这个接口,接收一个泛型T,返回泛型R,map函数的定义,返回的流,表示的泛型是R对象,这个表示,调用这个函数后,可以改变返回的类型
     */
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);

使用实例(将一个Integer类型的转换为一个Stringl类型):

public class ConvertType {
    public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        Stream.of(nums).map(intValue -> String.valueOf(intValue)).forEach( vo -> {
            System.out.println(vo);
            System.out.println(vo.getClass()); // class java.lang.String
        });
    }
}

从main方法执行的结果可以发现经过map的处理Stream中的对象已经从Integer --> String
要将其返回值类型也修改可以如下操作:

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        List<String> list = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.toList());
    }

2、Stream.collect()方法

一转为字符串:

直接使用Stream对象的collect方法传入Collectors.joining()),其中joining方法是一个重载方法。
使用一、直接joining()不传任何参数如下:

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        String str = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.joining());
        System.out.println(str);  // "12345678910"
        System.out.println(str.getClass()); // class java.lang.String
    }

使用二、传入一个类型为CharSequence的 delimiter参数,其作用是,根据输入的delimiter参数按遇到的顺序由delimiter作为分隔符分隔
其源码如下:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
        return joining(delimiter, "", "");
    }

具体使用如:

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        String str = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.joining("-"));
        System.out.println(str);  // "1-2-3-4-5-6-7-8-9-10"
        System.out.println(str.getClass()); // class java.lang.String
    }

使用三:joining(CharSequence delimiter,CharSequence prefix, CharSequence suffix),根据传入的delimiter顺序的分隔符进行分隔,根据传入的prefix作为前缀拼接串,根据suffix作为后缀串进行拼接。
源码如下:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix) {
        return new CollectorImpl<>(
                () -> new StringJoiner(delimiter, prefix, suffix),
                StringJoiner::add, StringJoiner::merge,
                StringJoiner::toString, CH_NOID);
    }

具体使用如:

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        String str = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.joining("-",
                "prefix", "suffix"));
        System.out.println(str);  // "prefix1-2-3-4-5-6-7-8-9-10suffix"
        System.out.println(str.getClass()); // class java.lang.String
    }

二:转为LIst
直接使用Stream对象的collect方法传入Collectors.toList())

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        List<String> list = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.toList());
        list.forEach(str -> System.out.println(str));
    }

三:转为Set
直接使用Stream对象的collect方法传入Collectors.toSet())

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        Set<String> set = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.toSet());
        set.forEach(str -> System.out.println(str));
    }

*四:转为Map
*

直接使用Stream对象的collect方法传入Collectors.toSet())
简单的对象转map:.

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        Map<String, String> map = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.
                toMap(String::toString, String::toString));
        Iterator<String> iterator = map.values().iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

如何考虑到可能存在hash冲突问题可以引入mergefunction作为参数
mergefunction方法源码如下:

Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
  Function<? super T, ? extends U> valueMapper,
  BinaryOperator<U> mergeFunction)

其作用是一个合并函数,它指出在发生冲突的情况下,我们保留现有条目,
具体使用如下:

public static void main(String[] args) {
        Integer[] nums = new Integer[]{1,1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        Map<String, String> map = Stream.of(nums).map(intValue -> String.valueOf(intValue)).collect(Collectors.
                toMap(String::toString, Function.identity(), (existing, replacement) -> existing));
        Iterator<String> iterator = map.values().iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

复杂对象转map.
首先先准备一个java对象如下:

public class Student {
    
    private String name;
    
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

具体使用如(使用具体的成员变量为key 和value):

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        Map<String, Integer> map = students.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
    }

或者使用对象作为value:

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        Map<String, Student> map = students.stream().collect(Collectors.toMap(Student::getName, Function.identity()));
        map.values().forEach(vo -> System.out.println(vo));
    }

或使用lambda表示设置key 和value:

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        Map<String, Student> map = students.stream().collect(Collectors
                // 第一个参数为key.
                // 第二为value;
                // 第三个表示前后的key是相同,到是覆盖还是不覆盖,(s1,s2)-> s1表示不覆盖,(s1,s2)-> s2 表示覆盖。
                .toMap(s -> s.getName(), s -> s, (s1, s2) -> s1));
        map.values().forEach(vo -> System.out.println(vo));
        System.out.println(map instanceof TreeMap); // true
    }

默认情况下,tomap()方法将返回哈希映射。我们可以使用这个重载的toMap()方法,toMap方法可以将一个Stream对象转换成一个Map对象。源码如下:

Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
  Function<? super T, ? extends U> valueMapper,
  BinaryOperator<U> mergeFunction,
  Supplier<M> mapSupplier)

其中mapsupplier是返回带有结果的新空映射的函数。

返回一个ConcurrentHashMap

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        Map<String, Student> map = students.stream().collect(Collectors.toMap(Student::getName, Function.identity(),
                (o1,o2) -> o1, ConcurrentHashMap::new
                ));
        map.values().forEach(vo -> System.out.println(vo));
        System.out.println(map instanceof ConcurrentHashMap); // true
    }

返回一个TreeMap

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        Map<String, Student> map = students.stream().collect(Collectors.toMap(Student::getName, Function.identity(),
                (o1,o2) -> o1, TreeMap::new
                ));
        map.values().forEach(vo -> System.out.println(vo));
        System.out.println(map instanceof TreeMap); // true
    }

Collectors类的tomap()方法。它允许我们从流中创建一个新的映射

五 groupingBy方法
groupingBy是能够根据字段进行分组。
具体使用实例:

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        // 根据学生姓名进行分组
        Map<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getName));
        map.values().forEach(vo -> System.out.println(vo));
    }

或统计重名:

public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("user1", 18));
        students.add(new Student("user2", 26));
        students.add(new Student("user3", 30));
        students.add(new Student("user4", 10));
        students.add(new Student("user4", 10));
        // 统计年纪相同的学生
        Map<String, Set<String>> collect = students.stream().collect(Collectors.
                groupingBy(Student::getName, Collectors.mapping(Student::getName, Collectors.toSet())));
        collect.values().forEach(vo -> System.out.println(vo));
    }