有关Java中的集合(1):List<T>和Set<T>
- IT业界
- 2025-09-18 08:24:01

学习目标 核心掌握List集合了解Set集合 1.List<T>
● java.util.List。有序列表。 ● List集合元素的特点:有序表示存取有序(因为有索引)而且可以重复 ● List常用实现类: ArrayList、LinkedList、Vector等
1.1 常用方法 1.2 使用方法 测试List集合的使用方法 private static void demo1() { List<Integer> numList = new ArrayList<>(); //1.新增 numList.add(100); numList.add(20); numList.add(10); numList.add(2); //2.删除 numList.remove(Integer.valueOf(20));//删除元素:20 numList.removeIf(new Predicate<Integer>() { @Override public boolean test(Integer num) { return Integer.valueOf(20).equals(num); } }); numList.removeIf(Integer.valueOf(20)::equals); //numList.clear(); //3.修改 Integer num = numList.set(0, 200); System.out.println("num:"+num); //4.查询 Integer num = numList.get(0); System.out.println(num); //5.其它方法 System.out.println(numList.size()); System.out.println(numList.contains(100)); System.out.println(numList.indexOf(20));//获得指定数据第一次出现的索引位置 -1 System.out.println(numList.lastIndexOf(20)); System.out.println(numList.isEmpty()); numList.sort();//对集合数据进行排序 default void sort(Comparator<? super E> c); numList.sort(Comparator.naturalOrder());//对于Integer而言 其实底层已经提供了排序规则 //List集合元素类型已经实现过Comparable接口的话,使用List.sort()建议这样写 numList.sort(Comparator.reverseOrder()); System.out.println(numList); numList.replaceAll(new UnaryOperator<Integer>() {//修改满足条件的多个数据 @Override public Integer apply(Integer integer) { if (integer != null) { if (integer >= 100) { integer = 1; } } return integer; } }); /* numList.replaceAll(integer->{ if (integer != null) { if (integer >= 100) { integer = 1; } } return integer; });*/ } 了解subList方法 private static void demo3() { List<String> list = new ArrayList<>(); Collections.addAll(list, "a", "b", "c", "abc", "ccc"); //List<T> subList(startIndex,endIndex); List<String> subList = list.subList(0, 3); //subList之后,对截取之后的集合对象执行更新操作,都会还原到原对象。 //截取的集合对象: 记着原集合对象的 root //subList.add("hello"); //subList.remove(0); //subList.set(0,"aaaa"); //截取之后,操作原集合(新增/遍历截取集合/删除/修改)。会出现ConcurrentModificationException。 list.remove(0);// 已经删除。modCount 触发的fail-fast System.out.println("subList:" + subList); System.out.println("list:" + list); //Arrays.asList();//数组转集合 List<String> stringList = Arrays.asList("a", "b", "c", "abc", "ccc"); stringList.add("hello"); System.out.println(stringList); } 1.3 遍历集合 private static void demo2() { //方便创建对象并添加多个集合数据 还要满足后期更新。操作集合的工具类 java.util.Collections List<String> list = new ArrayList<>(); Collections.addAll(list, "a", "b", "c", "abc", "ccc"); //遍历List集合-----> 任意一种方式都可以 //1.增强for for (String s : list) { System.out.println(s); } //2.迭代器/listIterator Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); System.out.println(s); } /*ListIterator<String> listIterator = list.listIterator(); while (listIterator.hasNext()) { String s = listIterator.next(); System.out.println(s); } System.out.println("-----------------"); //光标默认在最左端 while (listIterator.hasPrevious()) { String s = listIterator.previous(); System.out.println("s:"+s); }*/ //3.普通for int size = list.size(); for (int index = 0; index < size; index++) { System.out.println(list.get(index)); } //4.forEach list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); list.forEach(System.out::println); System.out.println(list); } 1.4 常用实现类● 有序的特点: (有2种解释) ● 1.有索引位置(新增的元素顺序与遍历时候的顺序一致的) ● 2.可以按照排序规则排序(升序/降序)
● 常见数据结构: ● 1. 数组 ● 2. 链表: 1.单向链表: 当前数据/元素/节点 下一个节点的引用。 2.双向链表: 上一个节点的引用 当前数据 下一个节点的引用。 ● 3. 红黑树 ● 4. hash表
实现类底层数据结构性能/效率线程安全ArrayList动态数组查询/修改效率高。新增/删除效率低不安全LinkedList双向链表查询/修改效率低。新增/删除效率高。不安全Vector动态数组单线程里面, 功能等价于ArrayList。并发,所有的功能性能偏低安全● ArrayList底层是数组。 因为数组内存空间连续所以查询性能较高(时间复杂度 O(1) ),删除元素和指定位置新增涉及到数组元素的移动 所以性能较低 ● LinkedList底层是双向链表 内存空间不连续;链表的查询性能较低(要么从头查 要么从尾部查询 O(n)),删除和新增性能较高(只需要改动前后2个节点)
1.4.1 ArrayList<T>● 创建集合对象的时候 使用泛型进行约束 ● 底层是数组 ,当调用无参构造的时候,内部数组第一次扩容长度为10;当调用有参构造的时候 直接new一个指定长度的数组(建议使用有参构造 给一个大概的容量值 避免内部多次扩容降低性能) ● 底层是数组 因为数组内存空间连续所以查询性能较高,删除元素和指定位置新增涉及到数组元素的移动 所以性能较低
1.层级
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable{} //RandomAccess: 快速随机访问。 空接口,标记接口。使用index遍历集合数据比迭代器效率快很多的。2.常用构造
1. ArrayList() ;// 创建ArrayList集合对象 并初始化容量为10.---->数组的length。 2. ArrayList(int initialCapacity);//指定初始化容量数据 推荐。10 //initialCapacity: 存储的最大元素个数/负载因子+1; 3. ArrayList(Collection<? extends E> c);//将一个集合的数据转换成ArrayList3.基本使用
/**
泛型 元素类型 加约束 */ public static void arrayListMethod() { ArrayList arrayList = new ArrayList(); arrayList.add(“abc”); arrayList.add(“123”); // 加了泛型之后 取出来的元素 直接就是String类型了 String str = arrayList.get(1); // 集合中都是对象 没有基本数据类型 ArrayList arrayList2 = new ArrayList<>(); arrayList2.add(123); } 1.4.2 LinkedList<T>● 底层是链表 双向链表 内存空间不连续 ● 链表的查询性能较低,删除和新增性能较高(新增与删除最多只需要改动前后2个节点)
1.层级
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable{} // 双链表实现了List和Deque接口。 实现所有可选列表操作,并允许所有元素(包括null )2.常用构造
1.LinkedList();//推荐使用 2.LinkedList(Collection<? extends E> c)3.基本使用
private static void demo1() { LinkedList<String> linkedList = new LinkedList<>(); //1.新增 /*linkedList.add("a"); linkedList.add(1,"b"); linkedList.addFirst("hello"); linkedList.addLast("abc"); linkedList.push("111");*///addFirst add(0,"111"); linkedList.add("a"); linkedList.add("b"); linkedList.add("c"); linkedList.add("d"); linkedList.offer("1");//add(); linkedList.offerFirst("0"); linkedList.offerLast("100"); //2.删除 linkedList.remove("a"); linkedList.remove(0); //删除第一个数据 linkedList.removeFirst(); //删除最后一个数据 linkedList.remove(linkedList.size() - 1); linkedList.removeLast(); linkedList.pollLast(); //3.修改 linkedList.set(0,"abc"); //4.查询 system.out.println(linkedList.get(0)); System.out.println(linkedList.getFirst()); System.out.println(linkedList.element()); System.out.println(linkedList.peek()); System.out.println(linkedList.peekFirst()); /*System.out.println(linkedList.get(linkedList.size() - 1)); System.out.println(linkedList.getLast()); System.out.println(linkedList.peekLast());*/ System.out.println(linkedList); } 1.4.3 Vector<T>● 底层也是数组,是一个线程安全的集合类. ● 线程安全的ArrayList的变体。 ● 根本原因: Vector中所有的方法都使用synchronized。 ● 了解此类即可。
1.层级
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable{}2.常用构造
1. Vector();//初始化容量为10 2. Vector(int initialCapacity) ;//建议使用3.线程安全
public class VectorDemo { //private static Vector<Integer> list = new Vector<>(100); private static List<Integer> list = Collections.synchronizedList(new ArrayList<>(100)); //需要将线程不安全的集合对象 转换成线程安全的集合对象 Collections.syn public static void main(String[] args) { demo2(); } private static void demo2() { //开启多个任务 多个线程 同时操作list对象 新增数据 //模拟: 创建10个线程 每个线程执行100次 add 1-100 1000个数据 List<Thread> threadList = new ArrayList<>(10); for (int i = 0; i < 10; i++) { threadList.add(new Thread(VectorDemo::forDemo)); } threadList.forEach(Thread::start);//启动10个线程 //必须等待前10个线程的死亡 try { for (Thread thread : threadList) { thread.join(); } } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("size:" + list.size());//1000 } private static void forDemo() { for (int num = 1; num <= 100; num++) { list.add(num); } } } 2.Set<T>● 实现了Set接口的实现类的集合元素数据: 无序 且不可重复 ● 实现类有:HashSet ,LinkedHashSet, TreeSet等 ● Set集合的每个数据都是作为Map的key来维护的。
2.1 常用方法在Set集合中,没有独有的方法。所有的方法都是继承的Collection父接口。
2.2 使用方法 private static void demo1() { Set<Integer> set = new HashSet<>();//唯一 无序 set.add(10); set.add(20); set.add(null); //删除 //set.remove(10); //..... System.out.println(set); System.out.println(set.size()); } 2.3 遍历集合 /** * Set 遍历方式有3种 因为没有索引 所以不能使用普通for循环 */ public static void demo2() { HashSet<String> hashSet = new HashSet<>(); hashSet.add("aa"); hashSet.add("bb"); hashSet.add("cc"); System.out.println("-----1---------"); for (String str : hashSet) { System.out.println(str); } System.out.println("------2---------"); Iterator<String> iterator = hashSet.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("--------3----------"); hashSet.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); hashSet.forEach((a) -> { System.out.println(a); }); hashSet.forEach(System.out::println); } 2.4 常用实现类 数据结构元素是否可以为null线程安全HashSethash表+位桶(数组)+单向链表+红黑树。(HashMap维护HashSet的数据)可以不安全LinkedHashSet双向链表+hash表。(LinkedHashMap)可以不安全TreeSet红黑树(TreeMap) 有序(自然顺序排列)平衡不可以不安全 2.4.1 HashSet<T>1.常用构造
1.HashSet() //HashMap实例具有默认初始容量(16)和负载因子(0.75)。 2.HashSet(int initialCapacity) // initialCapacity = 存储的最大的元素个数/负载因子+12.基本使用
private static void demo1() { HashSet<Integer> hashSet = new HashSet<>(); //hashSet.add(1); Collections.addAll(hashSet, 1, 10, 8, 100, 2, 80); hashSet.add(100); hashSet.add(null); //元素是完全没有顺序 新增顺序与遍历顺序不一样 //元素没有索引位置 System.out.println(hashSet); } 2.4.2 LinkedHashSet<T> LinkedHashSet是HashSet的子类。 private static void demo2() { LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>(); Collections.addAll(linkedHashSet, 1, 10, 8, 100, 2, 80,null,80); System.out.println(linkedHashSet); //新增的顺序与遍历的顺序一致的 } 2.4.3 TreeSet<T>1.常用构造
元素是有序(顺序)----> 按照自然顺序排列(排序)---->升序/降序 要求TreeSet集合的元素类型必须提供“排序规则”。 元素不能存储null(不能调用方法hashcode) 1. TreeSet() //根据其元素的自然排序进行排序. 要求集合元素类型必须实现java.lang.Comparable 2. TreeSet(Comparator<? super E> comparator) //自定义外部比较器对象 对集合元素进行排序2.基本使用
private static void demo3() { TreeSet<Integer> treeSet = new TreeSet<>();//会集合元素排序---->集合元素类型的排序规则---> Integer //前提是无参构造 默认按照升序进行排列 //treeSet.add(null); treeSet.add(10); treeSet.add(1); treeSet.add(0); treeSet.add(15); treeSet.add(12); System.out.println(treeSet); System.out.println("min:" + treeSet.first()); System.out.println("max:" + treeSet.last()); } 3.集合存储对象● 需求: 使用集合存储多个用户信息。
3.1 List<T> @Setter @Getter @AllArgsConstructor @NoArgsConstructor @ToString public class UserInfo { private Integer id; private String name; private Integer age; } private static void demo1() { //创建多个用户对象 存储到集合中 //ArrayList //List集合可以存储多个重复的数据 List<UserInfo> userInfoList = new ArrayList<>(10); userInfoList.add(new UserInfo(1, "张三", 20)); userInfoList.add(new UserInfo(1, "张三", 20)); userInfoList.add(new UserInfo(1, "张三", 20)); userInfoList.add(new UserInfo(1, "张三", 20)); userInfoList.forEach(System.out::println); } 3.2 HashSet<T> @Setter @Getter @AllArgsConstructor @NoArgsConstructor @ToString public class UserInfo { private Integer id; private String name; private Integer age; //重写hashcode+equals 定义2分对象相等的规则 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UserInfo userInfo = (UserInfo) o; return Objects.equals(name, userInfo.name) ; } @Override public int hashCode() { return Objects.hash( name); } //...... } private static void demo2() { //使用HashSet存储多个用户对象 //无序且唯一的 //使用Set存储自定义类型对象的时候 一定自己重写equals+hashcode 底层数据结构是重建hash //根据重写的equals+hashcode 判断对象是否是相同的对象 Set<UserInfo> userInfoSet = new HashSet<>(); userInfoSet.add(new UserInfo(1, "张三", 20)); userInfoSet.add(new UserInfo(2, "张三", 20)); userInfoSet.add(new UserInfo(3, "张三", 20)); userInfoSet.add(new UserInfo(4, "张三", 20)); userInfoSet.forEach(System.out::println); } 3.3 TreeSet<T>● TreeSet底层的数据结构是红黑树。 ● 由于TreeSet集合的元素要按照排序规则进行排序。所以使用TreeSet集合存储自定义类对象,一定要提供排序规则。 ● 可以根据不同的TreeSet构造创建对象: ● TreeSet(); 无参构造创建对象。要求集合元素类型必须实现Comparable接口。 ● TreeSet(Comparator comparator); 有参构造创建对象。集合元素类型不必实现Comparable,这个时候会使用外部比较器Comparator里面定义的排序规则对集合元素排序。
写法1: @Setter @Getter @AllArgsConstructor @NoArgsConstructor @ToString public class UserInfo implements Comparable<UserInfo> { private Integer id; private String name; private Integer age; //自定义排序规则 //不需要重写equals+hashcode TreeSet底层不是hash维护的,与这2个方法没有一点关系,只看排序规则。 //在排序规则里面,相关属性相同的对象就会认为是相同的对象。 @Override public int compareTo(UserInfo userInfo) { return userInfo.age pareTo(this.age); } } private static void demo3() { //使用TreeSet存储多个用户对象 //元素会排序----->排序规则是什么? //使用TreeSet无参构造创建对象 要求集合元素类型必须实现java.lang.Comparable //TreeSet与hash没有关系 底层是树结构维护的 只看排序规则里面的属性的数据 TreeSet<UserInfo> userInfoTreeSet = new TreeSet<>(); userInfoTreeSet.add(new UserInfo(1, "张三", 20)); userInfoTreeSet.add(new UserInfo(2, "张三", 20)); userInfoTreeSet.add(new UserInfo(3, "张三", 12)); userInfoTreeSet.add(new UserInfo(4, "张三", 25)); userInfoTreeSet.forEach(System.out::println); } 写法2: @Setter @Getter @AllArgsConstructor @NoArgsConstructor @ToString public class UserInfo { private Integer id; private String name; private Integer age; } private static void demo4() { // TreeSet<UserInfo> userInfoTreeSet = new TreeSet<>(new Comparator<UserInfo>(){ // @Override // public int compare(UserInfo user1, UserInfo user2) { // return user1.getAge() pareTo(user2.getAge()); // } // }); // TreeSet<UserInfo> userInfoTreeSet = new TreeSet<>((user1,user2)->user1.getAge() pareTo(user2.getAge())); TreeSet<UserInfo> userInfoTreeSet = new TreeSet<>(Comparator paring(UserInfo::getAge)); userInfoTreeSet.add(new UserInfo(1, "张三", 20)); userInfoTreeSet.add(new UserInfo(2, "张三", 20)); userInfoTreeSet.add(new UserInfo(3, "张三", 12)); userInfoTreeSet.add(new UserInfo(4, "张三", 25)); userInfoTreeSet.forEach(System.out::println); } }有关Java中的集合(1):List<T>和Set<T>由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“有关Java中的集合(1):List<T>和Set<T>”