Java集合[重点]

1. Collection接口和常用方法

  1. 集合主要是两组(单列集合,双列集合)
  2. Collection 接口有两个重要的子接口 ListSet,它们的实现子类都是单列集合
  3. Map 接口的实现子类 是双列集合,存放 K-V
  4. 梳理的两张图记住(必须背会)

image-20230913163807352

image-20230913163922897

1.1Collection 简介

package com.xjz.collection_;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class Collection_ {

    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //代码解读
        //1. 集合主要是两组(单列集合,双列集合)
        //2. Collection 接口有两个重要的子接口 List 和 Set,它们的实现子类都是单列集合
        //3. Map 接口的实现子类 是双列集合,存放 K-V
        //4. 梳理的两张图记住(必须背会)
        //Collection
        //Map
        ArrayList arrayList = new ArrayList();//单列集合
        arrayList.add("xjz");
        arrayList.add("2002");

        HashMap hashMap = new HashMap();//双列集合
        hashMap.put("No.1","北京");
        hashMap.put("No.2","上海");
    }
}

1.2 Collection 接口常用方法

package com.xjz.collection_;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class CollectionMethod {

    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        // add 添加单个元素
        list.add("xjz");
        list.add(10);
        list.add(true);
        System.out.println("list=" + list);
        // remove 删除指定元素
        //list.remove(0);//删除第一个元素
        list.remove(true);//删除指定元素
        System.out.println("list=" + list);

        // contains:查找元素是否存在
        System.out.println(list.contains("xjz")); //true

        //size: 获取元素个数
        System.out.println(list.size());//2

        //isEmpty:判断是否为空
        System.out.println(list.isEmpty());//false

        //clear:清空元素
        list.clear();
        System.out.println("list=" + list); //list=[]

        //addAll:添加多个元素
        ArrayList list2 = new ArrayList();
        list2.add("张三");
        list2.add("李四");
        list.addAll(list2);
        System.out.println("list=" + list); //list=[张三, 李四]

        //containsAll:查找多个元素是否存在
        System.out.println(list.containsAll(list2)); //true

        //removeAll:删除多个元素
        list.add("平凡的世界");
        list.removeAll(list2);
        System.out.println("list=" + list); //list=[平凡的世界]
        // 说明:以 ArrayList 实现类来演示..

    }
}

2. List 接口和常用方法

  1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复

  2. List 集合中的每个元素都有其对应的顺序所以,即支持索引

  3. List 容器中的元素都对应一个整数型的序号记载其 在容器中的位置,可以根据序号存取容器中的元素。

public class List_ {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //1. List 集合类中元素有序(即添加顺序和取出顺序一致)、且可重复
        List list = new ArrayList();
        list.add("jack");
        list.add("tom");
        list.add("xjz");
        list.add("tom");
        System.out.println("list=" + list);

        //2. List 集合中的每个元素都有其对应的顺序所以,即支持索引
        //   索引是从 0 开始的
        System.out.println(list.get(2)); //xjz
    }
}

2.1 List 接口的常用方法

package com.xjz.list_;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class ListMethod {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("张三丰");
        list.add("贾宝玉");

        // void add(int index, Object ele):在 index 位置插入 ele 元素
        //在 index = 1 的位置插入一个对象
        list.add(1,"xjz");
        System.out.println("list=" + list);// list=[张三丰, 徐金卓, 贾宝玉]

        // boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来
        List list2 = new ArrayList();
        list2.add("jack");
        list2.add("tom");
        list.addAll(1,list2);
        System.out.println("list=" + list); //list=[张三丰, [jack, tom], 徐金卓, 贾宝玉]

        // Object get(int index):获取指定 index 位置的元素
        System.out.println(list.get(2)); //tom

        // int indexOf(Object obj):返回 obj 在集合中首次出现的位置
        System.out.println(list.indexOf("tom")); //2

        // int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置
        list.add("xjz");
        System.out.println("list=" + list);
        System.out.println(list.lastIndexOf("xjz"));//5

        // Object remove(int index):移除指定 index 位置的元素,并返回此元素
        list.remove(0);
        System.out.println("list=" + list);//list=[jack, tom, xjz, 贾宝玉, xjz]

        // Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换.
        list.set(0,"xjz");
        System.out.println("list=" + list); //list=[xjz, tom, xjz, 贾宝玉, xjz]

        // List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合
        // 注意返回的子集合 fromIndex <= subList < toIndex  左闭右开区间
        List returnList = list.subList(0, 2);
        System.out.println("returnList=" + returnList);//returnList=[xjz, tom]

    }
}

3. ArrayList底层结构和Vector底层结构的比较

image-20230914102550254

package com.xjz.list_;

import java.util.ArrayList;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class ArrayListSource {
    public static void main(String[] args) {

        //ArrayList 源码解读
        //注意: Idea默认情况下,Debug 显示的数据是简化后的
        //使用无参构造器创建 ArrayList 对象
        //无参扩容:第一次添加数据 默认扩容为 10,第二次及以后都是 1.5倍扩容
        //ArrayList list = new ArrayList();
        ArrayList list = new ArrayList(8);

        //使用for 给 list集合添加 1-10 数据
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }

        //使用for 给 list 集合添加 11-15数据
        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
    }
}

image-20230914102512470

3.1 ArrayList 和 Vector 的比较

image-20230914101301313

3.2 ArrayList 和 LinkedList的比较

image-20230914132205308

image-20230914132229628

4. Set 接口实现类-HashSet

  1. 以 set 接口的实现类 HashSet 来讲解 Set 接口的方法
  2. set 接口的实现类的对象(Set 接口对象),不能存放重复的元素,可添加 一个 null
  3. set 接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)
  4. 注意:取出的顺序虽然不是添加的顺序,但是它是固定的,每次取出都是一样的顺序
package com.xjz.set_;

import java.util.HashSet;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class HashSet01 {
    public static void main(String[] args) {
        HashSet set = new HashSet();

        //说明
        //1. 在执行 add方法后,会返回一个 boolean值
        //2. 如果添加成功,返回 true,否则返回 false
        //3. 可以通过 remove 指定删除哪个对象
        System.out.println(set.add("john"));//T
        System.out.println(set.add("lucy"));//T
        System.out.println(set.add("john"));//F
        System.out.println(set.add("jack"));//T
        System.out.println(set.add("Rose"));//T

        set.remove("john");
        System.out.println("Set=" + set);//Set=[Rose, lucy, jack]

        set = new HashSet();
        System.out.println("set=" + set); //set=[]
        //4. Hashset 不能添加相同的元素/数据?
        set.add("lucy");
        set.add("lucy");
        set.add(new Dog("xjz"));//ok
        set.add(new Dog("xjz"));//ok
        System.out.println("set="+set);//set=[Dog{name='xjz'}, lucy, Dog{name='xjz'}]

        //再加深一下,非常经典的面试题
        //看源码,做分析
        //去看他的源码,即 add 到底发生了什么? =》 底层机制
        set.add(new String("tom"));//ok
        set.add(new String("tom"));//加入不了
        //no,因为它们两个底层都是指向常量池的"tom"地址,即指向同一个地址
        System.out.println("set=" + set);//set=[tom, Dog{name=xjz}, lucy, Dog{name=xjz}]

    }
}

class Dog { //定义了Dog类
    private String name;

    public Dog(String name) {
        this.name = name;
    }

    @Override
    public java.lang.String toString() {
        return "Dog{" +
                "name=" + name +
                '}';
    }
}

5. HashSet底层 扩容机制

image-20230914154510788

6. Set 接口实现类 - LinkedHashSet

image-20230914172045316

image-20230914172057831

package com.xjz.set_;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class LinkedHashSetSource {
    public static void main(String[] args) {

        Set set = new LinkedHashSet();
        set.add(new String("AA"));
        set.add(456);
        set.add(456);
        set.add(new Customer("刘",20));
        set.add(123);
        set.add("xjz");

        System.out.println("set=" + set); //set=[AA, 456, Customer{name='刘', age=20}, 123, xjz]

        //代码解读
        //1. LinkedHashSet 加入顺序和取出元素/数据的顺序一致
        //2. LinkedHashSet 底层维护的是一个 LinkedHashMap (是 HashMap 的子类)
        //3. LinkedHashSet 底层结构是 (数组table + 双向链表)
        //4. 添加第一次时,直接将 数组table 扩容到 16,存放的节点类型是 LinkedHashMap&Entry
        //5. 数组是 HashMap&Node[] 存放的元素/数据是 LinkedHashMap&Entry类型
    }
}

class Customer {
    private String name;
    private int age;

    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • 课后练习题 LinkedHashSetExercise.java

image-20230914183235277

package com.xjz.set_;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Objects;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class LinkedHashSetExercise {
    public static void main(String[] args) {

        LinkedHashSet linkedHashSet = new LinkedHashSet();
        linkedHashSet.add(new Car("奥拓", 1000));
        linkedHashSet.add(new Car("奥迪", 300000));
        linkedHashSet.add(new Car("奔驰", 400000));
        linkedHashSet.add(new Car("迈腾", 230000));
        linkedHashSet.add(new Car("奥迪", 300000));

        System.out.println("linkedHashset=" + linkedHashSet);
    }
}

/**
 * Car 类(属性:name,price), 如果 name 和 price 一样,
 * 则认为是相同元素,就不能添加。 5min
 */
class Car {
    private String name;
    private double price;

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "Car{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Car car = (Car) o;
        return Double.compare(car.price, price) == 0 &&
                Objects.equals(name, car.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, price);
    }
}

7. Map 接口和常用方法

image-20230914181906417

package com.xjz.map_;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xjz_2002
 * @version 1.0
 */
public class Map_ {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //代码解读
        //1. Map 与 Collection 并列存在,用于保存具有映射关系的数据 Key-Value(双列元素)
        //2. Map 中的 Key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中
        //3. Map 中的 key 不允许重复,原因和 HashSet 一样
        //4. Map 中的 value 可以重复
        //5. Map 的key 可以为 null,value 也可以为 null,
        // 注意 key 为 null,只能有一个,value 为 null,可以多个
        //6. 常用 String 类作为 Map 的 key
        //7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
        Map map = new HashMap();
        map.put("no1", "徐金卓");//k-v
        map.put("no2", "张无忌");//k-v
        map.put("no1", "张三丰");//当有相同的 key,就等价于 替换
        map.put("no3", "张三丰");//k-v
        map.put(null, null);//k-v
        map.put(null,"abc");//等价替换
        map.put("no4",null);//k-v
        map.put("no5",null);//k-v
        map.put(1,"赵敏");//k-v
        map.put(new Object(),"金毛狮王");//k-v

        //通过 get 方法,传入 key,会返回对应的 value
        System.out.println(map.get("no2"));//张无忌

        System.out.println("map=" + map);
    }
}

image-20230914183317569

8. Map 接口实现类-HashMap

8.1 HashMap 小结

image-20230915143343457

8.2 HashMap 底层机制及源码剖析

image-20230915152435629

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

9. Map 接口实现类 - Hashtable

  1. 默认初始化大小为 11, 加载因子0.75
    public Hashtable() {
    this(11, 0.75f);
    }
  2. 达到 临界值 8时,扩容 11 * 2 + 1 = 23 即 2倍 + 1
    int newCapacity = (oldCapacity << 1) + 1;

image-20230915152559716

package com.xjz.map_;

import java.util.Hashtable;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class Hashtable__ {
    public static void main(String[] args) {

        Hashtable hashtable = new Hashtable();
        hashtable.put("john",100);//ok
        //hashtable 不能存 null键 或 null值
//        hashtable.put(null,100);//异常
//        hashtable.put("john",null);//异常
        hashtable.put("lucy",200);//ok
        hashtable.put("lic",100);//ok
        hashtable.put("lic",300);//替换
        System.out.println(hashtable);

        /*
        1. 默认初始化大小为 11, 加载因子0.75
        public Hashtable() {
            this(11, 0.75f);
        }
        2. 达到 临界值 8时,扩容 11 * 2 + 1 = 23  即 2倍 + 1
            int newCapacity = (oldCapacity << 1) + 1;
           
         */
    }
}

10. HashTable 和 HashMap 对比

image-20230915152648388

11. Map 接口实现类 - Properties

image-20230915163040531

package com.xjz.map_;

import java.util.Properties;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class Properties_ {
    public static void main(String[] args) {

        //代码解读
        //1. Perperties 继承 Hashtable
        //2. 可以通过 k-v 存放数据,当然 key 和 value 不能为 null
        //增加
        Properties properties = new Properties();
//        properties.put(null,"abc");//抛出  空指针异常
//        properties.put("abc",null);//抛出 空指针异常
        properties.put("john", 100);//k-v
        properties.put("lucy", 100);
        properties.put("lic", 100);
        properties.put("lucy", "xjz");//如果有相同的 key,value 被替换

        System.out.println("properties=" + properties);

        //通过 k 获取对应值
        System.out.println(properties.get("lic"));//100

        //删除
        properties.remove("lic");
        System.out.println("properties=" + properties);

        //修改
        properties.put("john","张三");
        System.out.println("properties=" + properties);
    }
}

  • 总结-开发中如何选择集合实现类(记住)

image-20230915163130812

12. TreeSet 和 TreeMap

package com.xjz.set_;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class TreeSet_ {
    public static void main(String[] args) {

        //代码解读
        //1. 当我们使用无参构造器,创建 TrueSet时,仍然是无序的
        //2. 我们希望添加的元素,按照字符串大小排序
        //3. 使用 TreeSet 提供的一个构造器,可以传入一个比较器(匿名内部类)
        //   并指定排序规则
        //4. 简单看看源码
        /*
        1. 构造器把传入的比较器对象,赋给了 TreeSet 的底层的 TreeMap 的属性 this.comparator
        public TreeMap(Comparator<? super K> comparator) {
            this.comparator = comparator;
        }
        2. 在 调用 treeSet.add("tom"), 在底层会执行到

        if (cpr != null) {//cpr 就是我们的匿名内部类(对象)
            do {
                parent = t;
                //动态绑定到我们的匿名内部类(对象)compare
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else //如果相等,即返回 0,这个 Key 就没有加入
                    return t.setValue(value);
            } while (t != null);
        }
        */
        //TreeSet treeSet = new TreeSet();
        TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //下面调用 String 的 CompareTo方法,进行字符串大小比较
                //如果要求,按照字符串长度比较
//                return ((String) o1).compareTo((String)o2);
                return ((String)o1).length() - ((String)o2).length();
            }
        });
        //添加数据
        treeSet.add("tom");
        treeSet.add("jack");
        treeSet.add("jz");
        treeSet.add("a");

        System.out.println("treeSet=" + treeSet);
    }
}
  • TreeMap
package com.xjz.map_;

import java.util.Comparator;
import java.util.TreeMap;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class TreeMap_ {
    public static void main(String[] args) {

        //使用默认的构造器,创建 TreeMap,是无序的(也没有排序)
        //要求:按照传入的 k(String)的大小进行排序
//        TreeMap treeMap = new TreeMap();
        TreeMap treeMap = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String)o2);
            }
        });
        treeMap.put("jack","杰克");
        treeMap.put("tom","汤姆");
        treeMap.put("xjz","徐金卓");
        treeMap.put("jack","替换jack");//替换 value,key不变
        System.out.println("treeMap=" + treeMap);
    }
}

13. Collections 工具类

image-20230916100847898

image-20230916100909813

image-20230916102304210

package com.xjz.collctions_;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author xjz_2002
 * @version 1.0
 */
@SuppressWarnings({"all"})
public class Collections_ {
    public static void main(String[] args) {

        //创建 ArrayList 集合,用于测试.
        List list = new ArrayList(); //初始化10,扩容 1.5倍
        list.add("tom");
        list.add("smith");
        list.add("king");
        list.add("milan");
        list.add("tom");

        // reverse(List):反转 List 中元素的顺序
        Collections.reverse(list);
        System.out.println("list=" + list);
        // shuffle(List):对 List 集合元素进行随机排序
//        for (int i = 0; i < 5; i++) {
//            Collections.shuffle(list);
//            System.out.println("list=" + list);
//        }

        // sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
        Collections.sort(list); //升序
        System.out.println("===自然排序后===");
        System.out.println("list=" + list);

        //sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
        //我们希望按照 字符串的长度大小排序
        Collections.sort(list, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //可以加入校验代码
                //return ((String)o1).compareTo((String)o2);
                return ((String)o1).length() - ((String)o2).length();
            }
        });
        System.out.println("字符串长度大小排序=" + list);

        //swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
        Collections.swap(list,0,2);
        System.out.println("===交换后的情况===");
        System.out.println("list=" + list);

        //Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
        System.out.println("自然顺序最大元素=" + Collections.max(list));
        //Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
        //比如,我们要返回长度最大的元素
        Object maxObject = Collections.max(list, new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String)o2).length();
            }
        });
        System.out.println("长度最大的元素=" + maxObject);

        //Object min(Collection)
        //Object min(Collection,Comparator)
        //上面的两个方法,参考 max 即可

        //int frequency(Collection,Object):返回指定集合中指定元素的出现次数
        System.out.println("tom 出现的次数=" + Collections.frequency(list,"tom")); //2

        //void copy(List dest,List src):将 src 中的内容复制到 dest 中

        ArrayList dest = new ArrayList();
        //为了完成一个完整拷贝,我们需要先给 dest 赋值,大小和list.size()一样
        for (int i = 0; i < list.size(); i++) {
            dest.add("");
        }
        //拷贝
        Collections.copy(dest,list);
        System.out.println("dest=" + dest);

        //boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
        //如果 list 中,有 tom 就替换成 汤姆
        Collections.replaceAll(list, "tom", "汤姆");
        System.out.println("list=" + list);
    }
}

image-20230916115341253

image-20230916115817457

  • 为什么字符串 String类型的可以直接传入 TreeSet 集合中,因为String 底层已经实现了 Comparable接口

image-20230916120311273

image-20230916120955699

image-20230916121912897

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xjz_2002

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值