集合
集合

集合

集合

特点:自动扩容,可以储存引用类,如果存储基本数据类型需要变成包装类

ArrayList集合

package com.wsj.test7;

import java.util.ArrayList;

public class arratlistdemo1 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        //添加
        list.add("22");
        list.add("22");
        //删除
        boolean flag=list.remove("22");

        System.out.println(list);
        System.out.println(flag);

        //修改元素
        list.set(0,"ddd");
        System.out.println(list);
        for(int i=0;i<list.size();i++){
            String s=list.get(i);
            System.out.println(s);
        }
    }
}
方法 描述
add() 将元素插入到指定位置的 arraylist 中
addAll() 添加集合中的所有元素到 arraylist 中
clear() 删除 arraylist 中的所有元素
clone() 复制一份 arraylist
contains() 判断元素是否在 arraylist
get() 通过索引值获取 arraylist 中的元素
indexOf() 返回 arraylist 中元素的索引值
removeAll() 删除存在于指定集合中的 arraylist 里的所有元素
remove() 删除 arraylist 里的单个元素
size() 返回 arraylist 里元素数量
isEmpty() 判断 arraylist 是否为空
subList() 截取部分 arraylist 的元素
set() 替换 arraylist 中指定索引的元素
sort() 对 arraylist 元素进行排序
toArray() 将 arraylist 转换为数组
toString() 将 arraylist 转换为字符串
ensureCapacity() 设置指定容量大小的 arraylist
lastIndexOf() 返回指定元素在 arraylist 中最后一次出现的位置
retainAll() 保留 arraylist 中在指定集合中也存在的那些元素
containsAll() 查看 arraylist 是否包含指定集合中的所有元素
trimToSize() 将 arraylist 中的容量调整为数组中的元素个数
removeRange() 删除 arraylist 中指定索引之间存在的元素
replaceAll() 将给定的操作内容替换掉数组中每一个元素
removeIf() 删除所有满足特定条件的 arraylist 元素
forEach() 遍历 arraylist 中每一个元素并执行特定操作

底层基本原理

  1. 利用空参创建的集合,默认创建一个默认长度为0的数组
  2. 添加第一个元素的时候,创建一个新的长度为10的数组
  3. 存满时,会扩容1.5倍
  4. 如果一次性添加多个元素,大于1.5倍,数组的长度以实际情况为准

集合体系结构

collection:单列集合

Map:双列集合

List系列集合:添加的元素是有序、可重复、有索引

Set系列集合:添加的元素是无序、不重复、无索引

image-20250924190639831

Collection

单列集合的祖宗接口,它的功能是全部单列集合都可以继承使用的

public static void main(String[] args) {
        Collection<String> col=new ArrayList<>();
        //如果往List集合中添加元素。方法永远返回true
        //在Set集合中添加数据,如果不重复返回true.否则返回false
        col.add("a");
        col.add("b");
        col.add("c");
        System.out.println(col);
//        col.clear();
        System.out.println(col);
        col.remove("a");
        System.out.println(col);
        //底层依赖equals方法进行判断是否存在
        boolean result=col.contains("a");
    }

如果比较自定义数据类型,需要重写equals方法

collection的通用遍历方法

迭代器遍历

public static void main(String[] args) {
        Collection<String> col=new ArrayList<>();
        col.add("a");
        col.add("b");
        col.add("c");
        Iterator<String> it=col.iterator();
        while(it.hasNext()){
            String str=it.next();
            System.out.println(str);
        }
    }

遍历后指针不会复原

增强for遍历

为了简化迭代器代码

原理是一个iterator迭代器

所有的单列集合和数组才能使用增强for来进行遍历

Collection<String> col=new ArrayList<>();
        col.add("a");
        col.add("b");
        col.add("c");
        for(String s:col){
            System.out.print(s);
        }

Lambda表达式遍历

public static void main(String[] args) {
        Collection<String> col = new ArrayList<>();
        col.add("a");
        col.add("b");
        col.add("c");
//        col.forEach(new Consumer<String>() {
//            @Override
//            //s依次表示集合中的每一个数据
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });
        col.forEach(s ->
                System.out.println(s));

    }

List集合的方法

image-20250924203953027

泛型深入

泛型格式:<数据类型>

注意:泛型只能支持引用数据类型

好处:

统一数据类型

把运行时期的问题提前到了编译期间,避免了强制类型转换出现的异常,因为在编译阶段类型就能确定下来

方法泛型

定义在类中的泛型所有方法都能使用

定义在方法中的泛型只能本方法使用

接口泛型

实现类给出具体类型

实现类延续泛型,创建实现类对象时再确定类型

泛型的通配符

如果类型不确定,但是能知道以后只能传递某个继承体系中的,就可以使用泛型的通配符

Set集合

无序:存取顺序不一致

不重复:可以去除重复

无索引:不能通过for循环遍历,不能通过索引获取元素

Set实现的集合类

HashSet:无序、不重复、无索引

LinkedHashSet:有序、不重复、无索引

TreeSet:可排序、不重复、无索引

HashSet

底层采取哈希表存储数据

组成:

数组+链表+红黑树

哈希值:

根据hashCode方法算出来的int类型整数

一般会重写hashCode方法,利用对象内部的属性值计算哈希值

对象的哈希值特点:

如果没有重写hashCode方法,不同对象计算的哈希值是不同的

如果已经重写了Hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的

在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样

public int hashCode() {
        return Objects.hash(name, age);
    }
Student s1=new Student("zz",22);
        Student s2=new Student("zz",22);

        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());

底层原理:

创建一个默认长度为16,默认加载因子为0.75的数组,数组名为table

根据元素的哈希值和数组的长度计算出应该存入的位置

判断当前的位置是否为null,如果是null直接存入

如果位置不为null,表示有元素,则调用equals方法比较属性值

一样:不存

不一样:存入数组,形成链表

当链表长度超过8,而且数组长度大于等于64时,自动转换为红黑树

LinkedHashSet

底层结构依然是哈希表,只是每个元素有额外多了一个双链表记录存储的数据

如果要求去重且存取有序,才使用LinkedHashSet

TreeSet

特点:不重复,无索引,可排序

可排序:按照元素的默认规则排序

底层基于红黑树结构进行排序

默认规则:

对于数值类型:Integer,Double,默认按照从小到大的顺序进行排序

对于字符,字符串类型:按照字符串在ASCII码表中升序进行排序

TreeSet<Integer> ts=new TreeSet<>();
        ts.add(1);
        ts.add(2);
        ts.add(3);
        ts.add(4);
        Iterator<Integer> it=ts.iterator();
        while(it.hasNext()){
            int i=it.next();
            System.out.println(i);
        }
        for(int j:ts){
            System.out.println(j);
        }
        ts.forEach(integer -> System.out.println(integer));

两种比较方式

方式一:

默认排序规则

Student重写Compare接口的方法

public int compareTo(Student o) {
        //指定排序规则
        System.out.println("this:"+this);
        System.out.println("o:"+o);
        return this.getAge()-o.getAge();
    }
public int compareTo(Student2 o) {
        int sum1=this.getEnglish()+this.getChinese()+this.getMath();
        int sum2=o.getEnglish()+o.getChinese()+o.getMath();
        int i=sum1-sum2;
        i=i==0?this.getChinese()-o.getChinese():i;
        i=i==0?this.getEnglish()-o.getEnglish():i;
        i=i==0?this.getMath()-o.getMath():i;
        i=i==0?this.getAge()-o.getAge():i;
        i=i==0?this.getName().compareTo(o.getName()):i;
        return i;

    }

方式二:

创建集合时,自定义Comparator比较器对象,指定比较规则

public static void main(String[] args) {
        TreeSet<String> ts=new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //按照长度进行排序
                int i= o1.length()-o2.length();
                i=i==0? o1.compareTo(o2):i ;
                return i;

            }
        });
        ts.add("c");
        ts.add("ab");
        ts.add("df");
        ts.add("qwer");

        System.out.println(ts);
    }

如果两个规则同时存在以比较器对象为基准

总结:

想要集合中的元素可重复

用ArrayList集合

想要集合中的元素可以重复,且当前的增删操作明显多于查询

用LinkedList集合

如果想对集合中的元素进行去重

用HashSet集合,基于哈希表的

如果想对集合的元素进行去重,而且保证存取顺序

用LinkedList集合,基于哈希表和双链表,效率低于HashSet

如果相对集合中的元素进行排序

使用TreeSet集合

Map集合

Map集合的所有键是不允许重复的,但值是可以重复的,键和值是一一对应的,每一个键对应一个值

HashMap:无序,不重复,无索引

LinkedHashMap:有序,不重复,无索引

TreeMap:按照大小升序排序,不重复,无索引

public static void main(String[] args) {
        Map<String,Integer> map=new HashMap<>();
        map.put("zs",22);
        map.put("ws",23);
        map.put("rt",33);
        map.put("wf",33);
        map.put("ww",33);
        map.put("null",null);
        System.out.println(map);

        System.out.println(map.size());

        System.out.println(map.get("zs"));

        map.remove("zs");

        System.out.println(map.containsKey("zs"));
        System.out.println(map.containsValue(23));

        System.out.println(map.keySet());
        System.out.println(map.values());
    }

遍历方式

第一种:取出键值,遍历数据

Set<String> keys=map.keySet();
        for(String key:keys){
            Integer i=map.get(key);
            System.out.println(i);
        }

第二种:整体遍历

Set<Map.Entry<String,Integer>> entries=map.entrySet();
        for(Map.Entry<String,Integer> me:entries){
            String i=me.getKey();
            Integer j=me.getValue();
            System.out.println(i+j);
        }

第三种Lambda表达式

 map.forEach((s,integer)-> System.out.println(s+integer));

相关条目

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注