文章目录
1.集合概述
在没有学习集合前,基本都是用数组存储元素,而数组只适用于元素类型确定以及个数确定,不需要大量的增删的场景。集合却可以完美的解决上述问题,集合在未指定泛型参数时,默认的元素类型为Object,可以存储任意类型的数据,而且无需考虑集合的大小,因为集合的大小是可以动态变化的。所以集合非常适用于做增删元素的场景。
集合体系
在Java中集合分为两个大类,一是单列集合,二是双列集合。所谓的单例集合就是元素只能存储一个数组,而双列集合存储的是键值对。
2.Iterable
Iterable是可迭代的意思,作用是为集合类提供for-each循环的支持。
package java.lang; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; public interface Iterable<T> {//表示对象可以被迭代,它有个方法iterator方法,返回Iterator对象,实际通过Iterator接口的方法进行遍历 //类实现了iterable,就可以使用foreach //类没有实现则也可以创建Iterator的对象 Iterator<T> iterator(); //为了方便遍历并操作集合内的元素 default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } //提供了一个可以并行遍历元素的迭代器 default Spliterator<T> spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
3.Iterator
Iterator是foreach遍历的主体,它的源码如下:
package java.util; import java.util.function.Consumer; public interface Iterator<E> { //判断迭代的集合是否还有多个可以访问的元素,如果有则返回true,反之则false boolean hasNext(); //可以逐个访问集合中的每个元素,如果访问到集合末尾,该方法会抛出一个NoSuchElementException E next(); //删除上一次调用next()方法返回的元素 default void remove() { throw new UnsupportedOperationException("remove"); } //访问元素,指定访问的动作,直到再没有更多的元素,或者这个动作会抛出一个异常 default void forEachRemaining(Consumer<? super E> action) { Objects.requireNonNull(action); while (hasNext()) action.accept(next()); } }
3.1for-each的本质
for-each循环的实现也依赖于Iterator,只不过我们写的for-each在编译时会被转换成Iterator方式遍历。
代码示例
import java.util.ArrayList; /** * @author 929KC * @date 2022/11/8 15:01 * @description: */ public class Demo { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); for (Integer integer : list) { System.out.print(integer+" "); } } }
为了对上述结论验证,可以反编译(class->java)上述代码
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) // import java.util.ArrayList; import java.util.Iterator; public class Demo { public Demo() { } public static void main(String[] args) { ArrayList<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); Iterator var2 = list.iterator(); while(var2.hasNext()) { Integer integer = (Integer)var2.next(); System.out.print(integer + " "); } } }
反编译之后,可以看到所谓的for-each,实际上就是使用迭代器迭代。
4.Collcetion
Collection是一个接口,它提供了对集合中元素进行操作的通用接口方法。为各种具体的实现类,提供了最大化的统一操作。也就意味着把握住了该接口中的方法,就几乎拿其具体的实现类的方法。
package java.util; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; public interface Collection<E> extends Iterable<E> { //储存在集合中的元素个数 int size(); //判断集合是否为空 boolean isEmpty(); //判断集合是否包含某个元素 boolean contains(Object o); //返回一个迭代集合元素的迭代器 Iterator<E> iterator(); //将集合转换成Object数组 Object[] toArray(); //返回这个集合中对象的数组。如果a足够大,将集合中的元素填入这个数组中。剩余空间填补null;否则分配一个新数组,其成员类型与a的成员类型相同,其长度等于集合的大小,并填充集合元素 <T> T[] toArray(T[] a); //向集合添加元素 boolean add(E e); //删除集合中的某个元素 boolean remove(Object o); //判断该集合是否包含指定集合中的元素 boolean containsAll(Collection<?> c); //将c集合中的所有元素都添加到当前集合中,添加成功返回true,反之则false boolean addAll(Collection<? extends E> c); //从当前集合中删除c集合中的所有元素,删除成功返回true,反之则false boolean removeAll(Collection<?> c); //删除满足某个条件的元素 default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; } //从当前集合中删除c集合中没有的元素,删除成功返回true,反之则false boolean retainAll(Collection<?> c); //清空集合中的元素 void clear(); boolean equals(Object o); int hashCode(); }
Collection部分方法演示
package com.kc.collection; import org.junit.Test; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; public class CollectionTest { @Test public void ColletcionApl(){ Collection<String> list = new ArrayList(); list.add("叶秋涵"); list.add("叶子秋"); list.add("林黛玉"); list.add("贾宝玉"); ArrayList<String> list2 = new ArrayList<String>(); list2.add("史湘云"); list2.add("妙玉"); list2.add("秦可卿"); list.addAll(list2); Object[] objects = list.toArray(); System.out.println(Arrays.toString(objects)); System.out.println(list.contains("林黛玉")); System.out.println(list.size()); System.out.println(list.isEmpty()); System.out.println(list.containsAll(list2)); String [] s = new String [20]; String[] strings = list.toArray(s); System.out.println(Arrays.toString(strings)); String [] s2 = new String [7]; String[] strings2 = list.toArray(s2); System.out.println(Arrays.toString(strings2)); Predicate<String> predicate = new Predicate<String>() { @Override public boolean test(String s) { return s.equals("史湘云"); } }; System.out.println(list.removeIf(predicate)); System.out.println(list); list.forEach(e-> System.out.print(e)); } } //结果 //[叶秋涵, 叶子秋, 林黛玉, 贾宝玉, 史湘云, 妙玉, 秦可卿] //true //7 //false //true //[叶秋涵, 叶子秋, 林黛玉, 贾宝玉, 史湘云, 妙玉, 秦可卿, null, null, null, null, null, null, null, null, null, null, null, null, null] //[叶秋涵, 叶子秋, 林黛玉, 贾宝玉, 史湘云, 妙玉, 秦可卿] //true //[叶秋涵, 叶子秋, 林黛玉, 贾宝玉, 妙玉, 秦可卿] //叶秋涵叶子秋林黛玉贾宝玉妙玉秦可卿
5.Collections
Collections是操作集合的一个工具类,提供了大量的静态方法看以实现对集合元素的排序,添加一些元素,随机排序,替换等操作。
代码示例
package com.kc.collection; import org.junit.Test; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; public class CollectionTest { @Test public void testCollections(){ ArrayList<String> list = new ArrayList<>(); //一次性向集合添加多个元素 Collections.addAll(list,"林黛玉","妙玉","史湘云","张飞","贾宝玉","薛宝钗"); System.out.println("未排序前:"+list); //使用默认的随机源随机排列指定的列表。 System.out.println("随机排列指定前:"+list); Collections.shuffle(list); System.out.println("随机排列指定后:"+list); //将集合中元素按照默认规则排序。 System.out.println("自然排序前:"+list); Collections.sort(list); System.out.println("自然排序后:"+list); } } //运行结果 //未排序前:[林黛玉, 妙玉, 史湘云, 张飞, 贾宝玉, 薛宝钗] //随机排列指定前:[林黛玉, 妙玉, 史湘云, 张飞, 贾宝玉, 薛宝钗] //随机排列指定后:[林黛玉, 妙玉, 张飞, 薛宝钗, 史湘云, 贾宝玉] //自然排序前:[林黛玉, 妙玉, 张飞, 薛宝钗, 史湘云, 贾宝玉] //自然排序后:[史湘云, 妙玉, 张飞, 林黛玉, 薛宝钗, 贾宝玉]
自定义排序
代码示例
package com.kc.collection; import lombok.AllArgsConstructor; import lombok.Data; @Data @AllArgsConstructor public class Apple implements Comparable<Apple>{ private String name; private String color; private double price; private int weight; /** * 自定义比较规则 * @author 929KC * @date 2022/11/8 2022/11/8 * @param o * @return int */ @Override public int compareTo(Apple o) { // 按照重量进行比较的 return this.weight - o.weight ; // List集存储相同大小的元素会保留 } }
对苹果类型按照自定义规则排序
package com.kc.collection; import org.junit.Test; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; public class CollectionTest { @Test public void testCollections2(){ List<Apple> apples = new ArrayList<>(); // 可以重复! apples.add(new Apple("毒苹果", "黑色", 9.9, 500)); apples.add(new Apple("青苹果", "绿色", 15.9, 300)); apples.add(new Apple("红苹果", "功色", 29.9, 400)); apples.add(new Apple("黄苹果", "黄色", 9.8, 500)); // 方法一:Apple类已经重写了比较规则,可以使用 Collections.sort(apples); System.out.println(apples); //方式二:sort方法自带比较器对象 Collections.sort(apples, new Comparator<Apple>() { @Override public int compare(Apple o1, Apple o2) { return Double.compare(o1.getPrice() , o2.getPrice()); // 按照价格排序!! } }); System.out.println(apples); } } //运行结果 //[Apple(name=青苹果, color=绿色, price=15.9, weight=300), Apple(name=红苹果, color=功色, price=29.9, weight=400), Apple(name=毒苹果, color=黑色, price=9.9, weight=500), Apple(name=黄苹果, color=黄色, price=9.8, weight=500)] //[Apple(name=黄苹果, color=黄色, price=9.8, weight=500), Apple(name=毒苹果, color=黑色, price=9.9, weight=500), Apple(name=青苹果, color=绿色, price=15.9, weight=300), Apple(name=红苹果, color=功色, price=29.9, weight=400)]
终