一篇搞懂进阶集合使用技巧

一篇搞懂Stream流

文章目录

  • 一篇搞懂Stream流
    • 不可变集合(Java9特性)
      • 应用场景
      • 书写格式
      • 小案例
    • Stream流
      • 引入案例
      • Stream流的作用
      • Stream流的使用步骤
      • Stream流的中间方法
      • Stream流的终结方法

不可变集合(Java9特性)

不可以被修改的集合,一旦创建完毕长度和内容都不能更改

应用场景

  • 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是个很好的实践。
  • 当集合对象被不可信的库调用时,不可变形式是安全的。
  • 不想让别人修改集合中的内容

书写格式

在List、Set、Map接口中,都存在静态的of方法,可以获取一个不可变的集合,这个集合不能添加,不能删除,不能修改。

方法名称 说明
static List of(E…elements) 创建一个具有指定元素的List集合对象
static Set of(E…elements) 创建一个具有指定元素的Set集合对象
static Map of(E…elements) 创建一个具有指定元素的Map集合对象

小案例

  • List
public class ImmutableDemo1 {
    public static void main(String[] args) {
        /*创建不可变的List集合"张三","李四","王五","赵六"*/
        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        List<String> list = List.of("张三","李四","王五","赵六");

        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list.get(3));

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

        for (String s : list){
            System.out.println(s);
        }

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

        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

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

        for(int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }

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

        //list.remove("李四");
        //list.add("aaa");
        //list.set(0,"aaa");
    }
}
  • Set
public class ImmutableDemo2 {
    public static void main(String[] args) {
        /*创建不可变的Set集合"张三","李四","王五","赵六"
         细节: 获取不可变的Set集合时,里面的参数要保证唯一性
        */
       
        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Set<String> set = Set.of("张三","李四","王五","赵六");

        for (String s : set){
            System.out.println(s);
        }

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

        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s);
        }

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

        //set.remove("李四");
        //set.add("aaa");
        //set.set(0,"aaa");
    }
}
  • Map
public class ImmutableDemo3 {
    public static void main(String[] args) {
        /*创建不可变的Map集合
         细节: 键是不可重复的,Map里面的of方法参数有上限,最多存放20个
			因为可变参数只能放在最后,但键和值有两个可变参数,解决方法组合成键值对
        */
        //一旦创建完毕之后,是无法进行修改的,在下面的代码中,只能进行查询操作
        Map<String,String> map = Map.of("张三","南京","李四","北京","王五","上海","赵六","广州","孙七","深圳","周八","杭州","吴九","宁波","郑十","苏州","刘一","无锡","陈二","嘉兴");

        Set<String> keys = map.keySet();
        for (String key : keys){
            String value = map.get(key);
            System.out.println(key + ":" + value);
        }

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

        Set<Map.Entry<String,String>> entries = map.entrySet();
        for (Map.Entry<String,String> entry : entries){
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + ":" + value);
        }

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

        //list.remove("李四");
        //list.add("aaa");
        //list.set(0,"aaa");
    }
}
public class ImmutableDemo4 {
    public static void main(String[] args) {
        /*如果我们要传递多个键值对对象,数量大干10个,在Map接口中还有一个方法 */
        HashMap<String,String> hm = new HashMap<>();
        hm.put("张三","南京");
        hm.put("李四","北京");
        hm.put("王五","上海");
        hm.put("赵六","北京");
        hm.put("孙七","深圳");
        hm.put("周八","杭州");
        hm.put("吴九","宁波");
        hm.put("郑十","苏州");
        hm.put("刘一","无锡");
        hm.put("陈二","嘉兴");
        hm.put("aaa","bbb");

        //利用上面的数据获取一个不可变集合,获取到所有的键值对对象(Entry对象〉
        Set<Map.Entry<String,String>> entries = hm.entrySet();
        //把entries变成数组
        Map.Entry[] arr = entries.toArray(new Map.Entry[0]);
        //toArray方法在底层会比较集合的长度跟数组的长度两者的大小
        //如果集合的长度〉数组的长度: 数据在数组中放不下,此时会根据实际数据的个数,重新创建数组
        //如果集合的长度〈= 数组的长度: 数据在数组中放的下,此时不会创建新的数组,而是直接用   
        Map map = Map.ofEntries(arr);

        //以上代码可替换为下面一行
        //Map map= Map.ofEntries(hm.entryset().toArray(new Map.Entry[0]));

        //Java10新特性
        //Map map = Map.copyOf(hm);

        //map.put("bbb","ccc");
    }
}

Stream流

引入案例

优化前

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

        /*
        创建集合添加元素。完成以下需求:
        1.把所有以 张 开头的元素存储到新集合中
        2.把 张 开头的,长度为3的元素再存储到新集合中
        3.遍历打印最终结果
        */

        ArrayList<String> list1 = new ArrayList<>();
        list1.add("张无忌");
        list1.add("张三峰");
        list1.add("张良");
        list1.add("周芷若");

        //1.把所有以 张 开头的元素存储到新集合中
        ArrayList<String> list2 = new ArrayList<>();
        for (String name : list1) {
            if (name.startsWith("张")) {
                list2.add(name);
            }
        }

        System.out.println(list2);

        //2.把 张 开头的,长度为3的元素再存储到新集合中
        ArrayList<String> list3 = new ArrayList<>();
        for (String name : list2) {
            if(name.length() == 3){
                list3.add(name);
            }
        }

        System.out.println(list3);

        //3.遍历打印最终结果
        for (String name : list3) {
            System.out.println(name);
        }
    }
}

优化后

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

        /*
        创建集合添加元素。完成以下需求:
        1.把所有以 张 开头的元素存储到新集合中
        2.把 张 开头的,长度为3的元素再存储到新集合中
        3.遍历打印最终结果
        */

        ArrayList<String> list1 = new ArrayList<>();
        list1.add("张无忌");
        list1.add("张三峰");
        list1.add("张良");
        list1.add("周芷若");

        list1.stream()
            .filter(name -> name.startsWith("张"))
            .filter(name -> name.length() == 3)
            .forEach(System.out::println);
    }
}

Stream流的作用

结果了Lambda表达式,简化集合、数组操作

Stream流的使用步骤

  1. 先得到一条Stream流(流水线),并把数据放上去
  2. 使用中间方法对流水线上的数据进行操作
  3. 使用终结方法对流水线上的数据进行操作
获取方式 方法名 说明
单列集合 default Stream stream() Collection中的默认方法
双列集合 无法直接使用stream流
数组 public static Stream stream(T[] array) Arrays工具类中的静态方法
一堆零散数据 public static Stream of(T… values) Stream接口中的静态方法
public class StreamDemo2 {
    public static void main(String[] args) {
        /*
         单列集合          default stream stream()                       Collection中的默认方法
         双列集合              无                                           无法直接使用stream流
         数组             public static cT> Stream stream(T[] array)    Arrays 工具类中的静态方法
         一堆零散数据      public static Stream of(T... values)       Stream接口中的静态方法
        */

        //单列集合
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "A", "B", "C", "D", "E", "F", "G");
        list.stream().forEach(System.out::println);

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

        //双列集合
        HashMap<String, Integer> map = new HashMap<>();
        map.put("AA", 1);
        map.put("BB", 2);
        map.put("CC", 3);

        map.keySet().stream().forEach(System.out::println);
        System.out.println("~~~~~~~~");
        map.values().stream().forEach(System.out::println);
        System.out.println("~~~~~~~~");
        map.entrySet().stream().forEach(System.out::println);

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

        //数组
        int[] arr = {1, 2, 3, 4, 5};
        String[] arr2 = {"A", "B", "C", "D", "E"};

        Arrays.stream(arr).forEach(System.out::println);
        Arrays.stream(arr2).forEach(System.out::println);

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


        //一堆零散数据
        Stream.of(1, 2, 3, 4, 5, 6).forEach(System.out::println);
        Stream.of("A", "B", "C", "D", "E", "F", "G").forEach(System.out::println);

        //注意:
        // Stream接口中静态方法of的细节
        // 方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组
        // 但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当做一个元素,放到Stream当中。

    }
}

Stream流的中间方法

名称 说明
Stream filter(Predicate predicate) 过滤
Stream limit(long maxSize) 获取前几个元素
Stream skip(long n) 跳过前几个元素
Stream distinct() 元素去重,依赖(hashCode和equals方法)
static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流
Stream map(Function mapper) 转换流中的数据类型
  • 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
  • 修改Stream流中的数据,不会影响原来集合或者数组中的数据
public class StreamDemo3 {
    public static void main(String[] args) {
        /*
       filter   过滤
       limit    获取前几个元素
       skip     跳过前几个元素
       distinct 元素去重,依赖(hashcode和equals方法)
       concat   合并a和b两个流为一个流
        map      转换流中的数据类型
        */

        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌","周芷若","赵皈","张强","张三丰","张举山","王二麻子","谢广坤");

        // filter 过滤 把 张 开头的名字留下
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);

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

        // limit    获取前3个元素
        // skip     跳过前2个元素
        list.stream().limit(3).skip(2).forEach(System.out::println);

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

        // distinct 元素去重,依赖(hashcode和equals方法)
        // concat   合并a和b两个流为一个流
        ArrayList<String> list1 = new ArrayList<>();
        Collections.addAll(list1,"张无忌","张无忌","张无忌","张强","张三丰","张举山","张良","王二麻子","谢广坤");
        ArrayList<String> list2 = new ArrayList<>();
        Collections.addAll(list2,"周芷若","赵敏");

        list1.stream().distinct().forEach(System.out::println);

        Stream.concat(list1.stream(),list2.stream()).forEach(System.out::println);

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

        // map      转换流中的数据类型
        ArrayList<String> list3 = new ArrayList<>();
        Collections.addAll(list3, "张无忌-12", "张强-42", "张三丰-64", "张举山-11", "张良-98", "王二麻子-65", "谢广坤-54");
        //只获取年龄并进行打印
        list3.stream().map(s -> Integer.parseInt(s.split("-")[1])).forEach(System.out::println);
    }
}

Stream流的终结方法

名称 说明
void forEach(Consumer action) 遍历
long count() 统计
toArray() 收集流中的数据,放到数组中
collect(Collector collector) 收集流中的数据,放到集合中
public class StreamDemo4 {
    public static void main(String[] args) {
        /*
         void forEach(Consumer action)      遍历
         long count()                       统计
         toArray()                          收集流中的数据,放到数组中
         collect(Collector collector)       收集流中的数据,放到集合中(List Set Map)
        */

        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵皈", "张强", "张三丰", "张举山", "王二麻子", "谢广坤");

        //forEach()
        list.stream().forEach(System.out::println);

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

        //count()
        long count = list.stream().count();
        System.out.println(count);

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

        //toArray()
        //toArray方法的参数的作用:负责创建一个指定类型的数组
        //toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组当中
        //toArray方法的返回值:是一个装着流里面所有数据的数组
        Object[] arr = list.stream().toArray();
        String[] arr2 = list.stream().toArray(String[]::new);
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(arr2));

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

        //collect()
        ArrayList<String> list2 = new ArrayList<>();
        Collections.addAll(list2, "张无忌-男-12", "张强-男-42", "张三丰-男-64", "张举山-女-11", "张良-女-98", "王二麻子-男-65", "谢广坤-女-54");
        //收集List集合中的男性
        List<String> newList = list2.stream().filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toList());

         //收集Set集合中的男性
        Set<String> newSet = list2.stream().filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toSet());

        System.out.println(newList);
        System.out.println(newSet);

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

        //收集Map集合中的男性
        //参数一:键的生成规则:Function泛型一:表示流中每一个数据的类型,泛型二:表示Map集合中键的数据类型
        //参数二:值的生成规则:Function泛型一:表示流中每一个数据的类型,泛型二:表示Map集合中值的数据类型
        Map<String, Integer> newMap = list2.stream().filter(s -> "男".equals(s.split("-")[1]))
                .collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));
        System.out.println(newMap);
    }
}

你可能感兴趣的:(实用工具及技术篇,microsoft,stream流,集合)