当前位置: 首页 > news >正文

了解Java集合的概念和体系:Collection<T>、Collections与Stream的使用

学习目标

本文知识是对集合层级的介绍,应用开发中实际使用的是他们的子级,感兴趣的小伙伴或者想深入了解有关Java集合知识的朋友可以选择阅读!

Stream的方法使用使用部分代码块内大多有两种实现方式,是为了更好的理解方法底层的代码,不必过于深究,可以看懂链式应用的方法即可

  1. 核心掌握集合层级
  2. 了解Collection
  3. 了解Collections
  4. 了解Stream

1.集合概念

● 集合和数组一样也是容器,但是只能放对象
● 集合和数组相比,数组长度是固定的(一旦确定之后不能改动) 集合长度不限
● 数组中数组元素要求数据类型一致;集合中可以放任意的对象(只能是对象 ,只不过对象类型不要求一致)
● 集合中不能放基本数据类型,只能放对象
● 集合中有比较多的数据结构 可供选择

2.集合体系

在这里插入图片描述

3.集合分类

● 有2大类的集合: 存储的数据特征。
● 1、Collection接口: 数据只能是单值(一个个的数据) 每次存储一个元素/数据
● 问题: 元素是否可重复? 元素是否有序(索引位置)?
List: 元素有序可重复
Set: 元素无序且唯一

● 2、Map<K,V> 接口 : 数据必须是一组元素(2个数据) 有key–value
● key: 必须唯一
● value: 可以重复

4.Collection<T>

● java.util.Collection
● 表示集合层次的根接口。
● 存储单值元素。

4.1 层级

public interface Collection<E> extends Iterable<E>{}

4.2 常用方法

在这里插入图片描述

4.3 使用方法

  • 无泛型
public static void collectionMethod() {
        Collection arrayList = new ArrayList();
        Collection arrayList2 = new ArrayList();
        arrayList2.add(66);
        arrayList2.add(99);
        // 自动装箱  1 int-->Integer
        arrayList.add(10);
        String a = "abc";
        arrayList.add(99);
        System.out.println("添加是否成功:" + arrayList.add(a));
        System.out.println("集合是否为空,没有集合元素:" + arrayList.isEmpty());
        // Integer是不可变的 ,一旦改值 那就是新的对象
        System.out.println("移除Integer是否成功:" + arrayList.remove(2));
        // remove进行移除的时候,看集合中是否包含这个对象 如果有那么移除成功
//        System.out.println("移除stringBuilder是否成功:" + arrayList.remove(stringBuilder));
        System.out.println("集合中的元素个数:" + arrayList.size());
        String b = "abc";
        System.out.println("集合中是否包含某个元素:" + arrayList.contains(b));
        // 一次性 添加多个元素进来  
        //arrayList.addAll(arrayList2);
        System.out.println("addAll:" + arrayList);
        // arrayList.removeAll(arrayList2);// 只要元素和arrayList2相等 就删除
        System.out.println("removeAll:" + arrayList); //
        System.out.println("containsAll 全部包含: " + arrayList.containsAll(arrayList2));
        //移除所有元素
        arrayList.clear();
    }
  • 有泛型
private static void demo1() {

        //1.创建集合对象
        Collection collection = new ArrayList();

        //2.操作
        //2.1 新增
        collection.add("hello");
        collection.add("hello");
        collection.add(100);
        collection.add(true);
        collection.add(10.123);
        collection.add(null);
        collection.add(new UserInfo("张三"));

        //2.2 查看集合元素个数
        System.out.println(collection.size());

        //2.3 删除
        collection.remove("hello");
        collection.remove("hello");

       /* collection.removeIf(new Predicate() {
            @Override
            public boolean test(Object obj) {
                return "hello".equals(obj);
            }
        });*/
        //collection.removeIf("hello"::equals);
        //collection.clear();

        //2.4判断
        System.out.println(collection.contains(1000));
        System.out.println(collection.isEmpty());
        System.out.println(collection.size()==0);
        System.out.println(collection.size());
        System.out.println(collection.toString());//

    }

4.4 遍历集合

  • 集合迭代器常用方法
    在这里插入图片描述
private static void demo2() {
        Collection<Integer> collection = new ArrayList<>();
        //java.util.Collections工具类  操作集合元素静态方法  Arrays
        Collections.addAll(collection, 10, 20, 30, 1, 5);
        //遍历集合元素的方式: 其实就1种遍历集合的方式(迭代器)
        // 2. 增强for
        // 增强for遍历数组: class文件里面还是普通for循环
        // 增强for遍历集合: class文件里面使用的iterator遍历集合元素的
        for (Integer num : collection) {
            System.out.println("num:"+num);
        }

        // 3. Iterator<E> iterator()  获得集合的迭代器对象
        //3.1 获得集合的迭代器对象
        Iterator<Integer> iterator = collection.iterator();//集合的数据都在iterator里面了
        //3.2 判断光标之后是否有数据
        while (iterator.hasNext()){
            //3.3 获得光标之后的数据
            Integer num = iterator.next();
            System.out.println("num:"+num);
        }

        // 4. default void forEach(Consumer<? super T> action)   遍历集合元素  jdk1.8+
        /*collection.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer num) {
                System.out.println(num);
            }
        });*/

        collection.forEach(System.out::println);
        System.out.println(collection);
    }

4.5 集合转数组

private static void demo3() {
    Collection<Integer> collection = new ArrayList<>();
    collection.add(100);//装箱
    collection.add(200);
    collection.add(300);

    //集合转数组----> 数组操作比较复杂
    //3. default <T> T[] toArray(IntFunction<T[]> generator);
    //第3个方法  与第2个方法的思想一致的。 length=0
    Integer[] integers = collection.toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {//0
                System.out.println("value:" + value);
                return new Integer[value];
            }
        });
    Integer[] integers = collection.toArray(Integer[]::new);
    System.out.println("integers:"+Arrays.toString(integers));


    //2. <T> T[] toArray(T[] a);  建议使用  核心:数组
    Integer[] numArray = new Integer[0];
    //2.1 length==collection.size() 保证数组里面存储size个元素
    //2.2 length>collection.size() 问题: 数组的空间比较大的 null----> 功能实现  有可能会出现NPE
    //2.3 length<collection.size() 可以转换成功
    //站在并发/性能/扩容: 建议指定的数组的length=0

    Integer[] toArray = collection.toArray(numArray);
        System.out.println("numArray:" + Arrays.toString(numArray));
        System.out.println("toArray:" + Arrays.toString(toArray));
        System.out.println(numArray == toArray);


    Object[] array = collection.toArray();
        //1. 不要使用Object[] toArray() 不管集合里面存储什么类型的数据  都要转成一个Object[]
        for (Object obj : array) {
             Integer num = (Integer) obj;
            System.out.println(num + 100);
        }
        System.out.println(Arrays.toString(array));
}

4.6 匿名内部类

● 在任意一个类和接口都能创建匿名内部类,相当于定义了一个 没有名字的新的类。
● 等价于创建了一个类的子类,以及接口的实现类。

  • 创建接口
public interface MyInterface {
    void method1();
}
  • 创建匿名内部类
public static void main(String[] args) {
    // 匿名内部类  抽象类 和接口都能使用
    test(new MyInterface() {
        @Override
        public void method1() {
            System.out.println("method111===");
        }
    });//等价于接口的实类对象
}

public static void test(MyInterface myInter) {
    myInter.method1();
}
public static void test1(){
    Object obj =  new Object(){
        //等价于类的匿名内部类---->类的子类
    }
}

提醒(可以先看这部分)

● 虽然我们讲解了集合的根接口Collection以及相关的方法。
● 但是在开发中一般不用父接口,用的还是子级,List或者Set
● 我们只需要知道Collection里面维护的都是List以及Set集合都有的方法即可。

5.Collections的使用

● 工具类。在java.util包。
● 类似于之前学的Arrays。
● Collections操作集合(Collection->List/Set)元素的工具类

  • 常用方法
private static void demo1() {
        //1.Collections.addAll(Collection,T...data); 将多个数据新增到指定的集合对象中
        List<Integer> list = new ArrayList<>(10);
        //list.add(10);
        Collections.addAll(list, 10, 10, 1, 3, 4, 50, 24, 100);

        Set<Integer> set = new HashSet<>(16);
        Collections.addAll(set, 10, 10, 1, 3, 4, 50, 24, 100);

        List<Integer> list1 = List.of(1, 2, 3);//只能读数据
        Set<Integer> set1 = Set.of(1, 2, 3, 4, 5);
        Map<Integer, Integer> map = Map.of(1, 1, 2, 2, 3, 3, 4, 4);

        //数组转集合
        List<Integer> list2 = Arrays.asList(1, 2, 3);
}
  • 常用的静态常量
private static List<?> demo3() {
        //获得一个空集合对象  等价于size=0
        System.out.println(Collections.EMPTY_LIST);//[]
        System.out.println(Collections.EMPTY_MAP);//{}
        System.out.println(Collections.EMPTY_SET);//[]
        System.out.println(Collections.emptySet());
        System.out.println(Collections.emptyMap());
        System.out.println(Collections.emptyList());

        //前提: 方法的返回值是特定的集合类型
        //在功能里面 可以作为返回值使用  判断的时候避免出现NPE
        return Collections.EMPTY_LIST;
    }

 private static void demo2() {
        //2.将线程不安全的集合对象转换成线程安全的集合对象  可以在并发的环境下  作为全局变量使用
        Collections.synchronizedList(new ArraysList());  Vector
        Collections.synchronizedSet(new HashSet())
        Collections.synchronizedMap(new HashMap())  ConcurrentHashMap
        //以下2个方法 只针对于TreeMap与TreeSet
        Collections.synchronizedSortedMap(new TreeMap())
        Collections.synchronizedSortedSet(new TreeSet())
    }
  • sort
private static void demo4() {
        //Collections.sort(List); 要求集合元素类型必须实现Comparable
        //Collections.sort(List,Comparator);
        //如果真的是对list集合排序,一般我们只会使用List.sort()
        List<Integer> list = new ArrayList<>(10);
        Collections.addAll(list, 10, 10, 1, 3, 4, 50, 24, 100);
        Collections.sort(list);
        System.out.println(list);

        System.out.println("-----------------------");
        List<UserInfo> userInfoList = new ArrayList<>(10);
        Collections.addAll(userInfoList,
                new UserInfo(1, "jim", 20),
                new UserInfo(2, "tom", 18),
                new UserInfo(3, "lilei", 23),
                new UserInfo(4, "hanmeimei", 16)
        );

        //Collections.sort(userInfoList, Comparator.comparing(UserInfo::getAge));
        userInfoList.sort(Comparator.comparing(UserInfo::getAge).reversed());
        userInfoList.forEach(System.out::println);
    }
  • 获得集合的最值
private static void demo5() {
        TreeSet<Integer> set = new TreeSet<>();
        Collections.addAll(set, 10, 10, 1, 3, 4, 50, 24, 100);
        System.out.println(set);//[1, 50, 3, 4, 100, 24, 10]
        //获得Set集合的最值
        //1.TreeSet
        System.out.println(set.first());
        System.out.println(set.last());

        System.out.println("------------------------------------");
        Set<Integer> hashSet = new HashSet<>(16);
        Collections.addAll(hashSet, 10, 10, 1, 3, 4, 50, 24, 100);
        //Collections.sort(List); 只能对list集合排序  不能对set集合排序
        //5. 最值
        Collections.max(Collection);  集合元素类型必须实现Comparable
        Collections.max(Collection,Comparator);
        Collections.min(Collection);
        Collections.min(Collection,Comparator);
        Integer max = Collections.max(hashSet);
        Integer min = Collections.min(hashSet);
        System.out.println(max);
        System.out.println(min);

    }
  • shuffle
 private static void demo6() {
    // Collections.shuffle(List); 随机(随机数)打乱集合元素顺序。 洗牌。
    List<Integer> list = new ArrayList<>(10);
    Collections.addAll(list, 10, 1, 3, 4, 50, 24);
    System.out.println(list);
    Collections.shuffle(list);
    System.out.println(list);
}

6.Stream

● 丰富了对Collection(List,Set)的操作
● 可以看成是一个增强版的迭代器。数据源不限,可以是多个数据源(Collection集合对象)
中间操作 属于 惰性操作 只有碰到终止操作才会执行
○ 凡是返回值是Stream类型的都是中间操作
○ filter:对流中数据进行过滤:返回值为
true表示留下的数据
false表示过滤掉的
○ map: 把流中的每个数据经过相同的操作 映射为新的数据
○ sorted:对流中数据排序
○ limit :只保留指定个数的元素
○ peek:表示查看 流中元素
终止操作
○ 只要返回值不是Stream类型的
○ count:得到流中元素个数
○ reduce:合并 合并为一个数据
○ collect:流数据的收集
● Stream对象流是一次性的,只能被操作一次,不能重复操作
● 终止操作只能出现一次,在最后出现

6.1 获得Stream

private static void demo1() {
    //获得Stream的方式
    //1. 根据集合对象操作。Collection.stream()/paraStream()
    List<Integer> list = Arrays.asList(1, 2, 3, 4);
    Stream<Integer> stream = list.stream();//串行化流  集合的数据都在Stream里面
    Stream<Integer> stream1 = list.parallelStream();//并行化流
    Iterator<Integer> iterator = list.iterator();
    //2. 使用Stream接口里面的静态方法
    Stream.concat(Stream,Stream);
    Stream<Integer> stream2 = Stream.of(1, 2, 3);

    //3.Arrays.stream()
    //IntStream  LongStream  DoubleStream
    //避免过多拆箱和装箱  提供了操作基本数据类型数据的Stream
    IntStream stream2 = Arrays.stream(new int[]{1, 2, 3});

    //4.Random.ints()
    //随机数Random
    //获得10个随机的数字。  0 200随机的数据
    Random random = new Random();
    int num = random.nextInt(200);
    IntStream intStream = random.ints(10, 100, 200);

    String str = "hello";
    IntStream intStream1 = str.chars();

}

6.2 操作Stream

  1. Stream Stream.distinct() ; 去重
  2. Stream Stream.sorted() ; 排序
  3. Stream Stream.sorted(Comparator<? super T> comparator) ; 根据外部比较器排序规则排序
  4. Stream Stream skip(long n); 跳过数据源里面指定数量的数据
  5. Optional Stream.max(Comparator<? super T> comparator) ; 获得最值
  6. Optional Stream.min(Comparator<? super T> comparator) ;
  7. Stream.limit(long maxSize) ; 对数据源的数量限定
  8. Stream.forEach(Consumer<? super T> action) 循环遍历
  9. Stream.count(); 统计Stream里面的元素个数
  10. Stream.findAny() ; 查询任意一个数据
  11. Stream.findFirst() ;
  12. collect(Collector<? super T,A,R> collector) //收集操作之后的数据 存储到一个新的集合对象中

1.distinct/sort

private static void demo2() {

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 20, 2, 1, 3);
    //对list集合元素进行去重/排序(降序)
        //1.获得Stream对象
        Stream<Integer> stream = list.parallelStream();
        //2.操作Stream
        Stream<Integer> stream1 = stream.distinct();
        Stream<Integer> stream2 = stream1.sorted(Comparator.reverseOrder());
        //3.获得操作之后满足条件的一些数据  存储到一个新的集合中---->收集起来  终止Stream
        List<Integer> resultList = stream2.collect(Collectors.toList());
        System.out.println(resultList);*/

    //Stream就是一次性的。
    //查询Stream里面还有多少个数据  终止Stream之后  无法再对Stream的数据进行相关的处理

    //操作Stream: 一般都是方法链的方式
    List<Integer> list1 = list.parallelStream().distinct().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
    System.out.println(list1);
}

2.allMatch/anyMatch

private static void demo3() {
        List<String> list = List.of("hellom", "jiy", "toc");
        //判断list集合的每个元素是否都包含指定的 m这个数据
       for (int index = 0; index < list.size(); index++) {
            String str = list.get(index);
            if(str==null) break;
            if(!str.contains("m")){
                System.out.println(false);
                return;
            }
        }
        System.out.println(true);
  System.out.println("----------------------------");
       boolean flag = list.parallelStream().allMatch(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("m");
            }
        });
        boolean flag = list.stream().anyMatch(str -> str.contains("m"));
        System.out.println(flag);
}

3.filter

Stream filter(Predicate<? super T> predicate) ;//过滤Stream中不满足条件的数据

private static void demo4() {
    List<String> list = List.of("zhangsan", "jim", "tom","lisi");
    //获得list集合中: 过滤下来元素里面包含m的数据
    List<String> nameList = new ArrayList<>(10);
        for (String name : list) {
            if(name.contains("m")){
                nameList.add(name);
            }
        }
    System.out.println("----------------------------");
    List<String> stringList = list.parallelStream()
        .filter(name -> name.contains("m")).collect(Collectors.toList());
    System.out.println(stringList);
}

4.findFirst/findAny/min

private static void demo5() {
    List<UserInfo> userInfoList = new ArrayList<>(10);
    Collections.addAll(userInfoList,
            new UserInfo(1, "jim", 20),
            new UserInfo(2, "tom", 18),
            new UserInfo(3, "lilei", 23),
            new UserInfo(4, "hanmeimei", 16)
    );
    //获得年龄>=20的用户
    List<UserInfo> collect = userInfoList.stream().filter(userInfo -> userInfo.getAge() >= 20).collect(Collectors.toList());
    //使用lambda表达式
    collect.forEach(System.out::println);


    //获得userInfoList年龄最小的用户对象
    //1.正常编写
    userInfoList.sort(Comparator.comparing(UserInfo::getAge));
    UserInfo userInfo = userInfoList.get(0);
    System.out.println(userInfo);
    System.out.println("-------------------");
    userInfoList.forEach(System.out::println);
    //或用Collections.min()

    //2.Stream
    Optional<UserInfo> first = userInfoList.stream().sorted(Comparator.comparing(UserInfo::getAge)).findFirst();
    System.out.println(first);
    System.out.println("-------------------");
    userInfoList.forEach(System.out::println);


   System.out.println("----------------------------");
    UserInfo userInfo = userInfoList.parallelStream().findAny().orElse(null);
    System.out.println(userInfo);
}

5.map/peek

场景: Stream里面的每个元素都要执行一样的功能的时候 。
//将stream里面的每个数据转换成另外一个类型的数据。

private static void demo6() {
    List<UserInfo> userInfoList = new ArrayList<>(10);
    Collections.addAll(userInfoList,
                       new UserInfo(1, "jim", 20),
                       new UserInfo(2, "tom", 18),
                       new UserInfo(3, "lilei", 23),
                       new UserInfo(4, "hanmeimei", 16)
                      );

    //将集合里面每个用户的name的数据全部转换成大写字母
    for (UserInfo userInfo : userInfoList) {
            userInfo.setName(userInfo.getName().toUpperCase());
        }
    //获得集合里面每个用户对象的name的属性数据  全部转大写字母存储
    List<String> collect = userInfoList.parallelStream().map(new Function<UserInfo, String>() {
            @Override
            public String apply(UserInfo userInfo) {
                return userInfo.getName().toUpperCase();
            }
        }).collect(Collectors.toList());


    List<String> collect = userInfoList.parallelStream()
        .map(userInfo -> userInfo.getName().toUpperCase()).collect(Collectors.toList());

    collect.forEach(System.out::println);

    System.out.println("-----------------------------");
    userInfoList.forEach(System.out::println);

}
private static void demo7() {
    List<UserInfo> userInfoList = new ArrayList<>(10);
    Collections.addAll(userInfoList,
                       new UserInfo(1, "jim", 20),
                       new UserInfo(2, "tom", 18),
                       new UserInfo(3, "lilei", 23),
                       new UserInfo(4, "hanmeimei", 16)
                      );
    List<UserInfo> collect = userInfoList.stream().map(new Function<UserInfo, UserInfo>() {
            @Override
            public UserInfo apply(UserInfo userInfo) {
                userInfo.setName(userInfo.getName().toUpperCase());
                return userInfo;
            }
        }).collect(Collectors.toList());
    /* List<UserInfo> collect = userInfoList.stream().map(userInfo -> {
            userInfo.setName(userInfo.getName().toUpperCase());
            return userInfo;
        }).collect(Collectors.toList());*/

    //前提: 对Stream的元素都执行同样的功能 最后集合里面的元素类型与原集合数据类型一致  建议使用peek替换map

    List<UserInfo> collect = userInfoList.parallelStream()
        .peek(userInfo -> userInfo.setName(userInfo.getName().toUpperCase())).collect(Collectors.toList());
    System.out.println(collect);
    System.out.println(userInfoList);
}

6.flatMap

private static void demo8() {

        List<Integer> list1 = List.of(1, 2, 30, 4, 5);
        List<Integer> list2 = List.of(10, 27, 3, 40, 5);
        List<Integer> list3 = List.of(11, 2, 3, 4, 5);
        List<Integer> list4 = List.of(100, 21, 3, 4, 50);

        //获得前5个数据(降序)+去重
        //核心: 将多个集合数据转换到一个集合中.

        List<Integer> collect = Stream.of(list1, list2, list3, list4).flatMap(List::stream)
                .distinct().sorted(Comparator.reverseOrder()).limit(5).collect(Collectors.toList());
        System.out.println(collect);
        /*Stream.of(list1, list2, list3, list4).flatMapToInt(new Function<List<Integer>, IntStream>() {
            @Override
            public IntStream apply(List<Integer> list) {
                return list.stream().mapToInt(Integer::intValue);
            }
        })*/
        Stream.of(list1, list2, list3, list4)
                .flatMapToInt(list -> list.stream().mapToInt(Integer::intValue))
                .distinct().sorted().limit(5).forEach(System.out::println);
    }

7.reduce

private static void demo9() {
    List<Integer> list = List.of(89, 90, 98);
    int sum = 0;
        for (Integer integer : list) {
            sum+=integer;
        }

    Integer sum1 = list.stream().reduce(new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer num1, Integer num2) {
                //System.out.println(num1+":"+num2);
                return num1 + num2;
            }
        }).orElse(null);




    Integer sum1 = list.stream().reduce(Integer::max).orElse(null);
    System.out.println(sum1);
}

相关文章:

  • 【中等】707.设计链表
  • 移动零
  • centos 下dockers部署surveyking-docker开源考试系统
  • 【数据结构与算法】Java描述:第一节:ArrayList顺序表
  • 使用watch监听route对象的变化
  • 【面试题】高并发场景下如何实现积分排行榜
  • R 语言科研绘图 --- 箱线图-汇总
  • 配置后端验证功能之validation
  • C++基础语法9——函数结构
  • Kotlin 5种单例模式
  • 了解什么是红黑树
  • 通过查询hive的元数据库中的表分区清单,拼写出来删除表分区的sql脚本
  • uniapp 中引入使用uView UI
  • PH热榜 | 2025-03-02
  • Sparsely-Gated Mixture-of-Experts Layer (MoE)论文解读与Pytorch代码实现
  • 大数据-236 离线数仓 - 会员活跃度 WDS 与 ADS 导出到 MySQL 与 广告业务 需求分析
  • 开启mysql的binlog日志
  • 【网络安全 | 渗透测试】GraphQL精讲一:基础知识
  • 高频 SQL 50 题(基础版)_1174. 即时食物配送 II
  • 随机播放音乐 伪随机
  • 怎么设置网站标题/珠海网络推广公司
  • 微网站医院策划案/微信营销软件群发
  • 企业产品网站模板/什么是关键词举例说明
  • 建设网站需要多大域名空间/线上营销活动主要有哪些
  • 遵义市做网站的地方/搜索引擎广告图片
  • 深圳做律师网站公司/优搜云seo