印尼建设银行网站上海松江网站设计公司
学习目标
本文知识是对集合层级的介绍,应用开发中实际使用的是他们的子级,感兴趣的小伙伴或者想深入了解有关Java集合知识的朋友可以选择阅读!
Stream的方法使用使用部分代码块内大多有两种实现方式,是为了更好的理解方法底层的代码,不必过于深究,可以看懂链式应用的方法即可
- 核心掌握集合层级
- 了解Collection
- 了解Collections
- 了解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-->IntegerarrayList.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() {@Overridepublic 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工具类 操作集合元素静态方法 ArraysCollections.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>() {@Overridepublic 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=0Integer[] integers = collection.toArray(new IntFunction<Integer[]>() {@Overridepublic Integer[] apply(int value) {//0System.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=0Integer[] 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() {@Overridepublic 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=0System.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());//前提: 方法的返回值是特定的集合类型//在功能里面 可以作为返回值使用 判断的时候避免出现NPEreturn Collections.EMPTY_LIST;}
private static void demo2() {//2.将线程不安全的集合对象转换成线程安全的集合对象 可以在并发的环境下 作为全局变量使用Collections.synchronizedList(new ArraysList()); VectorCollections.synchronizedSet(new HashSet())Collections.synchronizedMap(new HashMap()) ConcurrentHashMap//以下2个方法 只针对于TreeMap与TreeSetCollections.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.TreeSetSystem.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); 集合元素类型必须实现ComparableCollections.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//避免过多拆箱和装箱 提供了操作基本数据类型数据的StreamIntStream 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
- Stream Stream.distinct() ; 去重
- Stream Stream.sorted() ; 排序
- Stream Stream.sorted(Comparator<? super T> comparator) ; 根据外部比较器排序规则排序
- Stream Stream skip(long n); 跳过数据源里面指定数量的数据
- Optional Stream.max(Comparator<? super T> comparator) ; 获得最值
- Optional Stream.min(Comparator<? super T> comparator) ;
- Stream.limit(long maxSize) ; 对数据源的数量限定
- Stream.forEach(Consumer<? super T> action) 循环遍历
- Stream.count(); 统计Stream里面的元素个数
- Stream.findAny() ; 查询任意一个数据
- Stream.findFirst() ;
- 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.操作StreamStream<Integer> stream1 = stream.distinct();Stream<Integer> stream2 = stream1.sorted(Comparator.reverseOrder());//3.获得操作之后满足条件的一些数据 存储到一个新的集合中---->收集起来 终止StreamList<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>() {@Overridepublic 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.StreamOptional<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>() {@Overridepublic 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>() {@Overridepublic 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替换mapList<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>() {@Overridepublic 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>() {@Overridepublic 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);
}