Java集合

单列集合

集合框架

在这里插入图片描述

Collection接口的使用

  1. 概述:单列集合的顶级接口

  2. 使用:

    • 创建:Collection 对象名 = new 实现类对象()
    • :泛型,决定了集合中能存储什么类型的数据,可以统一数据类型
    • 泛型中只能写引用数据类型,如果不写,默认Object类型,此时什么类型的数据都可以存储
  3. 泛型细节:我们等号前面的泛型必须写,等号后面的泛型可以不写,jvm会根据前面的泛型推导出后面的泛型是什么

  4. 常用方法:

    boolean add(E e):将给定的元素添加到当前集合中,返回的是Boolean类型
    boolean addAll(Collection<? extends E> c):将另一个集合元素添加到当前集合中(集合合并)
    void clear():清除集合中的所有元素
    boolean contains(Object o):判断当前集合中是否包含指定元素
    boolean isEmpty():判断当前集合中是否为空
    boolean remove(Object o):将指定的元素从集合中删除
    int size():返回集合中的元素个数
    Object[] toArray():把集合中的元素,存储到数组当中
    

List接口

  1. 概述:是Collection接口的子接口

  2. 常见的实现类:
    ArrayList、 LinkedList 、Vector

ArrayList集合

  1. 概述:ArrayList是List接口的实现类

  2. 特点:
    元素有序 -> 按照什么顺序存的就按照什么顺序取
    元素可重复
    有索引 -> 可以利用索引去操作元素
    线程不安全

  3. 数据结构:数组

  4. 常用方法:

    boolean add(E e) -> 将元素添加到集合当中,尾部添加
    void add(int index, E element) -> 在指定索引位置添加元素
    boolean remove (Objrct o) -> 删除指定的元素
    E remove(int index) -> 删除指定索引位置上的元素,返回的是被删除的元素
    E set(int index, E element) -> 将指定索引位置上的元素,修改成后面的element元素
    E get(int index) -> 根据索引获取元素
    int size() -> 获取集合元素个数
    
  5. 集合的遍历

import java.util.*;
public class hhh {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("=================");
        for (String s : list) {
            System.out.println(s);
        }
        System.out.println("=================");
        //遍历带有索引的快捷键:集合名.fori
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}

ArrayList构造方法:
ArrayList() 构造一个初始容量为10的空列表
ArrayList(int initialCapacity) 构造一个具有指定初始容量的空列表
注意:
不是一new底层就会创建一个初始容量为10的空列表,而是第一次add的时候
ArrayList底层会自动扩容 -> Arrays.copyOf -> 扩容1.5倍

LinkedList集合

  1. 概述:LinkedList是List接口的实现类

  2. 特点:
    元素有序
    元素可重复
    有索引 -> 这里有索引指的是有操作索引的方法,不代表本质上有索引
    线程不安全

  3. 数据结构:双向链表

  4. 方法:有大量直接操作首尾元素的方法

    public void addFirst(E e) -> 将指定元素插入此链表的开头
    public E removeFirst() -> 删除并返回此链表的第一个元素
    public void addLast(E e) -> 
    public E removeLast() -> 
    public E getFirst() -> 返回此列表的第一个元素
    public E getLast() -> 
    public E pop() -> 从此列表的堆栈中弹出一个元素,第一个
    public void push(E e) -> 将元素推入此列表所表示的堆栈,第一个
    public void isEmpty(E e) -> 判断列表是否为空
    
  5. LinkedList底层成员解释说明

    • LinkedKList底层成员
      transient int size = 0;元素个数
      transient Node first;第一个节点对象
      transient Node last;最后一个结点对象
    • Node代表的是节点对象

Vector集合

  1. 概述:Vector是List的实现接口

  2. 特点:
    元素有序
    有索引
    元素可重复
    线程安全

  3. 数据结构:数组

  4. 如果空参创造对象,数组初始容量为10,如果超出范围,自动扩容2倍
    如果有参创造对象,如果超出了范围,自动扩容,扩的是老数组长度 + 指定容量的增量

import java.util.Vector;
public class HashTable {
    public static void main(String[] args) {
        Vector<String> strings = new Vector<>();
        strings.add("aa");
        strings.add("bb");
        for (String string : strings) {
            System.out.println(string)
        }
    }
}

Collections集合工具类

  1. 概述:集合工具类

  2. 特点:
    构造私有
    方法都是静态的

  3. 类名直接调用

  4. 常用方法与示例

import java.util.*;
public class hhh {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        //static <T> boolean addAll(Collection<? super T>c, T...element) -> 批量添加元素
        Collections.addAll(list, "a", "e", "c", "d", "f", "g", "h");
        System.out.println(list);
        //static void shuffle(List<?> list) -> 将集合中的元素顺序打乱
        Collections.shuffle(list);
        System.out.println(list);
        //static <T> void sort(List<T> list) -> 将集合中的元素进行排序--> ASCII码表
        Collections.sort(list);
        System.out.println(list);
    }
}
  • 元素按指定规则排序
  static <T> void sort(List<T> list, Comparator<? super T> c) -> 将集合的元素按照指定规则排序
  • Comparator比较器
2.  方法:
    int compare(T o1, T o2)
    	o1-o2 -> 升序
    	o2-o1 -> 降序
    
public class student {
    private String name;
    private int age;
    public student() {

    }
    public student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "student [name=" + name + ", age=" + age + "]";
    }
}

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

public class studentTest {
    public static void main(String[] args) {
        ArrayList<student> stu = new ArrayList<>();
        stu.add(new student("zz",24));
        stu.add(new student("pp",29));
        stu.add(new student("qq",26));
//        Collections.sort(stu);//报错,里面三个对象,不知道按照什么排序
         Collections.sort(stu,new Comparator<student>() {
             @Override
             public int compare(student o1, student o2) {
                 return o1.getAge()-(o2.getAge());
             }
         });
         System.out.println(stu);
    }
}

输出
    [student [name=zz, age=24], student [name=qq, age=26], student [name=pp, age=29]]
  • 接口:Comparable接口
方法:
    int compareTo(T o) -> this-o(升序)  o-this(降序)
    
public class student implements Comparable<student>{
    private String name;
    private Integer score;
    public student(String name, Integer score) {
        this.name = name;
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getScore() {
        return score;
    }
    public void setScore(Integer score) {
        this.score = score;
    }
    public String toString() {
        return "name: " + name + ", score: " + score;
    }
    @Override
    public int compareTo(student student) {
        return this.getScore() - student.getScore();
        //return this.score.compareTo(student.score);
    }
}

import java.util.ArrayList;
import java.util.Collections;

public class studentTest {
    public static void main(String[] args) {
        ArrayList<student> students = new ArrayList<>();
        students.add(new student("pp",23));
        students.add(new student("py",24));
        students.add(new student("pt",28));
        students.add(new student("pg",26));
        System.out.println(students);
        Collections.sort(students);//已经知道怎么排列,因此不报错
        System.out.println(students);
    }
}

输出
    [name: pp, score: 23, name: py, score: 24, name: pt, score: 28, name: pg, score: 26]
	[name: pp, score: 23, name: py, score: 24, name: pg, score: 26, name: pt, score: 28]
  • 拓展方法:Arrays中的静态方法
    static <T> List<T> asList(T...a) -> 指定元素转存到list集合中
    
import java.util.Arrays;
import java.util.List;

class erweishuzu {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("整数", "天天", "哈哈", "密码");
        System.out.println(list);//[整数, 天天, 哈哈, 密码]
    }
}

泛型

  1. 泛型<>

  2. 作用:统一数据类型,防止将来的数据转换异常

  3. 注意:
    泛型中的类型必须是引用数据类型
    如果泛型不写,默认类型为Object

为什么使用泛型

  1. 从使用层面来说:统一数据类型,防止将来的数据类型转换异常
import java.util.ArrayList;

class erweishuzu {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("1");
        list.add(2);
        list.add("abc");
        list.add(true);
        for(Object o : list){
            String s = (String) o;
            System.out.println(s.length()); //从第二个开始报错
        }
    }
}
  1. 从定义层面来看:定义带泛型的类、方法等,将来使用的时候给泛型确定什么类型,泛型就会变成什么类型,凡是涉及到泛型的都会变成确定的类型,代码更灵活

泛型的定义

  1. 含有泛型的类
1.定义:
    public class 类名<E>{
        
    }
2.什么时候确定类型:new对象的时候确定类型
    
import java.util.Arrays;
public class erweishuzu <E>{
        Object[] obj = new Object[10];
        int size;
        public boolean add(E e){
            obj[size] = e;
            size++;
            return true;
        }
        public E get(int index){
            return (E)obj[index];
        }
        @Override
        public String toString() {
            return Arrays.toString(obj);
        }
}
public class ptakaoshi {
    public static void main(String[] args) {
        erweishuzu<String> objecterweishuzu = new erweishuzu<>();
        objecterweishuzu.add("aaa");
        objecterweishuzu.add("bbb");
        System.out.println(objecterweishuzu); //[aaa, bbb, null, null, null, null, null, null, null, null]
        erweishuzu<Integer> objecterweishuzu1 = new erweishuzu<>();
        objecterweishuzu1.add(1);
        objecterweishuzu1.add(2);
        objecterweishuzu1.add(3);
        System.out.println(objecterweishuzu1); //[1, 2, 3, null, null, null, null, null, null, null]
        Integer ele = objecterweishuzu1.get(0);
        System.out.println(ele); //1
    }
}
  1. 含有泛型的方法
1.格式:
    修饰符 <E> 返回值类型 方法名(E e)
2.什么时候确定类型:调用的时候确定类型
    
import java.util.ArrayList;
public class erweishuzu <E>{
    public static <E> void addAll(ArrayList<E> list,E...e){
        for(E e1 : e){
            list.add(e1);
        }
    }
}
import java.util.ArrayList;

public class ptakaoshi {
    public static void main(String[] args) {
        ArrayList<String> objects = new ArrayList<>();
        erweishuzu.addAll(objects,"a","b","c","d","e","f","g","h","i");
        System.out.println(objects); //[a, b, c, d, e, f, g, h, i]
        ArrayList<Integer> list2 = new ArrayList<>();
        erweishuzu.addAll(list2,1,2,3,4,5,6,7,8,9);
        System.out.println(list2); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
    }
}
  1. 含有泛型的接口
1.格式:
	public interface 接口名<E>{
    
	}
2.什么时候确定类型:
    在实现类的时候还没有确定类型,只能在new实现类的时候确定类型了 -> 比如:ArrayList
	在实现类的时候直接确定类型了 -> 比如Scanner
public interface Mylist <E>{
    public boolean add(E e);
}
import java.util.Arrays;
public class Mylist1 <E> implements Mylist<E> {
    Object[] obj = new Object[10];
    int size = 0;
    public boolean add(E e) {
        obj[size] = e;
        size++;
        return true;
    }
    public E get(int index) {
        return (E) obj[index];
    }
    public String toString(){
        return Arrays.toString(obj);
    }
}
public class Text1 {
    public static void main(String[] args) {
        Mylist1<String> list1 = new Mylist1<>();
        list1.add("An");
        list1.add("Bn");
        System.out.println(list1);//[An, Bn, null, null, null, null, null, null, null, null]
    }
}
public interface MySca <E>{
    E next();
}
public class Myscann implements MySca <String>{
    @Override
    public String next() {
        return "hhh";
    }
}
public class Text2 {
    public static void main(String[] args) {
        Myscann myscann = new Myscann();
        String result = myscann.next();
        System.out.println(result); //hhh
    }
}

泛型的高级使用

  1. 泛型通配符
import java.util.*;
public class hhh {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("a");
        list1.add("b");
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(1);
        list2.add(2);
        method(list1);
        method(list2);
    }
    public static void method(ArrayList<?> list) {
        for(Object o : list) {
            System.out.println(o);
        }
    }
}
  1. 泛型的上限下限
1.作用:可以规定泛型的范围
2.上限:
    格式:<? extends 类型>
    含义:?只能接收extends后面的本类类型以及子类类型
3.下限:
	格式:<? super 类型>
    含义:?只能接收super后面的本类类型以及父类类型

应用场景:

  1. 如果我们在定义类、方法、接口的时候,如果类型不确定,我们可以考虑定义含有泛型的类、方法、接口
  2. 如果类型不确定,但是能知道以后只能传递某个类的继承体系中的子类或者父类,就可以使用泛型的通配符

Set集合

Set接口属于Collection接口的另外一个子接口,并没有对Collection进行任何功能上的扩充,而且所有的set集合底层都是依靠Map实现的

Set集合介绍

  1. Set和Map密切相关
  2. Map的遍历要先变成单列集合,只能变成Set集合

HashSet集合的介绍和使用

  1. 概述:HashSet是Set接口的实现类

  2. 特点:
    元素唯一
    元素无序
    无索引
    线程不安全

  3. 数据结构:哈希表
    jdk8之前:哈希表 = 数组 + 链表
    jdk8之后:哈希表 = 数组 + 链表 + 红黑树(加入红黑树是为了查询快)

  4. 方法:和collection一样

  5. 遍历:增强for、迭代器

import java.util.HashSet;
import java.util.Iterator;
public class koko1 {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("一样");
        set.add("会将");
        set.add("雨哦");
        System.out.println(set);
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        for (String s : set) {
            System.out.println(s);
        }
    }
}

LinkedHashSet集合的介绍和使用

  1. 概述:LinkedHashSet继承HashSet

  2. 特点:
    元素唯一
    元素有序
    无索引
    线程不安全

  3. 数据结构:哈希表 + 双向链表

  4. 使用:与父类一样

import java.util.Iterator;
import java.util.LinkedHashSet;
public class koko1 {
    public static void main(String[] args) {
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.add("一样");
        set.add("会将");
        set.add("雨哦");
        System.out.println(set);
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        for (String s : set) {
            System.out.println(s);
        }
    }
}

TreeSet

  1. 概述:TreeSet是set的实现类

  2. 特点:
    对元素进行排序
    无索引
    不能存null
    线程不安全
    元素唯一

  3. 数据结构:红黑树

构造:
    TreeSet() -> 构造一个新的空树集,根据其元素的自然顺序进行排序。-> ASCII
    TreeSet(Comparator<? super E> comparator) -> 构造一个新的空树集,根据指定的比较器排序。
    
public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" + "name=" + name + ", age=" + age + '}';
    }
}

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

public class PersonText {
    public static void main(String[] args) {
        TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-(o2.getAge());
            }
        });
        persons.add(new Person("hh",16));
        persons.add(new Person("jj",19));
        persons.add(new Person("gg",12));
        System.out.println(persons); 
        //[Person{name=gg, age=12}, Person{name=hh, age=16}, Person{name=jj, age=19}]
    }
}
哈希值
  1. 概述:是由计算机计算出来的一个十进制数,可以看作是对象的地址值

  2. 获取对象的哈希值,使用的是Object中的方法

    public native int HashCode()
    
  3. 如果重写了hashCode方法,那计算的就是对象内容的哈希值了

  • 哈希值不一样,内容肯定不一样
  • 哈希值一样,内容也有可能不一样

集合遍历方式

迭代器

基本使用
  1. 概述:Iterator接口

  2. 主要作用:遍历集合

  3. 获取:Collection中的方法:

    Iterator<E> iterator()
    
  4. 方法:

    boolean hasNext() -> 判断集合中有没有下一个元素
        E next() -> 获取下一个元素
    
import java.util.ArrayList;
import java.util.Iterator;
public class dieDai1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        //获取迭代器对象
        Iterator<String> iterator  = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());//A B C D
        }
    }
}
迭代过程
int cursor; //下一个元素索引位置
int lastRet = -1; //上一个元素索引位置
底层原理
1.获取Iterator的时候怎么获取的:
	Iterator iterator = list.iterator()
    Iterator是一个接口,等号右边是他的实现类对象,接收的是ArrayList中的内部类Itr对象

注意:只有ArrayList使用迭代器的时候iterator接口才会指向Itr,其他的就不指向了

并发修改异常
import java.util.ArrayList;
import java.util.Iterator;
public class A1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = iterator.next();
            if("C".equals(s)){
                list.add("e");
            }
        }
        System.out.println(list);
    }
}
输出报错:
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1096)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1050)
	at PPPttt.A1.main(A1.java:15)

迭代器内部维护了一个expectedModificationCount,即预期的操作次数,当集合的实际修改次数与这个计数不匹配时(当预期操作次数和实际操作次数不相等了),就会抛出ConcurrentModificationException(并发修改异常)

使用迭代器迭代集合的过程中,不要随意修改集合长度,容易出现并发修改异常

补充

ArratList中的方法:ListIterator listIterator

在Java中,ListIterator<E>Iterator<E> 接口的一个扩展,专门为 List 接口的实现类提供额外的操作。ListIterator 允许程序员对列表进行双向迭代,即既可以向前迭代也可以向后迭代,这与只能单向迭代的普通 Iterator 不同。

ArrayList 类实现了 List 接口,因此它提供了 listIterator() 方法来创建和返回一个 ListIterator 对象。

  • ListIterator 的特点:
  1. 双向迭代ListIterator 可以调用 next() 方法来获取下一个元素,也可以调用 previous() 方法来获取上一个元素。
  2. 修改列表ListIterator 允许在迭代过程中修改列表(通过 add(E e)set(E e) 方法)。
  3. 获取当前位置ListIterator 提供了 nextIndex()previousIndex() 方法来获取当前迭代位置的索引。
  4. 检查可迭代方向hasNext()hasPrevious() 方法用来检查迭代器是否有下一个或上一个元素。
  • ListIterator 的基本操作:
    • add(E e): 在 next()previous() 调用之后,可以在列表中的当前位置插入一个元素。
    • hasNext(): 如果迭代器有更多元素进行正向遍历,则返回 true
    • next(): 返回迭代器中的下一个元素并前进。
    • hasPrevious(): 如果迭代器有更多元素进行反向遍历,则返回 true
    • previous(): 返回迭代器中的上一个元素并后退。
    • set(E e): 用指定的元素替换最后一次由 next()previous() 返回的元素。
    • nextIndex(): 返回下一个调用 next() 方法时返回的元素的索引。
    • previousIndex(): 返回下一个调用 previous() 方法时返回的元素的索引。

增强for

  1. 基本使用

    • 作用:遍历集合或者数组
    • 格式:
      for(元素类型 变量名:要遍历的集合名或者数组名){
      变量名就是代表的每一个元素
      }
    • 快捷键:集合名或者数组名.for
    import java.util.ArrayList;
    
    public class LinkList {
        public static void main(String[] args) {
            ArrayList<String> s = new ArrayList<>();
            s.add("a");
            s.add("b");
            s.add("c");
            for (String st : s) {
                System.out.println(st);
            }
            int[] a = {1,2,3,4,5};
            for(int i : a){
                System.out.println(i);
            }
        }
    }
    
  2. 注意

    1.增强for遍历集合时,底层实现原理为迭代器
    2.增强for遍历数组时,底层实现原理为普通for
    

    所以不管是用迭代器还是使用增强for,在遍历集合的过程中都不要随意修改集合长度,否则会出现并发修改异常

双列集合

在这里插入图片描述

HashMap

HashMap的介绍和使用

  1. 概述:HashMap是Map的实现类

  2. 特点:
    key唯一,value可重复 -> 如果key重复了,会发生value覆盖
    无序
    无索引
    线程不安全
    可以存null键null值

  3. 数据结构:哈希表

  4. 常用方法:

    V put(K key, V value) -> 添加元素,返回的是被覆盖的value
    V remove(Object key) -> 根据key删除键值对,返回的是被删除的value
    V get(Object key) -> 根据key获取value
    boolean containsKey(Object key) -> 判断集合中是否包含指定的key
    判断集合中是否包含指定的value
            boolean v5 = map.containsValue("d");
    Collection<V> values() -> 获取集合中所有的value,转存到Collection集合中
    

LinkedHashMap

  1. 概述:LinkedHashMap extends HashMap
  2. 特点:
    key唯一,value可重复 -> 如果key重复了,会发生value覆盖
    有序
    无索引
    线程不安全
    可以存null键null值
  3. 数据结构:哈希表 + 双向链表
  4. 使用:和HashMap一样

HashMap的两种遍历方式

  1. 获取key,根据key再获取value

    Set<K> KeySet() ->Map中的Key获取出来,转存到Set集合中
    
    import java.util.LinkedHashMap;
    import java.util.Set;
    public class HashMap1 {
        public static void main(String[] args) {
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            map.put("a", "b");
            map.put("c", "d");
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                String value = map.get(key);
                System.out.println(key + "=" + value);
            }
        }
    }
    
  2. 同时获取key和value

    Set<Map,Entry<K,V>> entrySet() -> 获取Map集合中的键值对,转存到Set集合中
    
    import java.util.*;
    public class HashMap1 {
        public static void main(String[] args) {
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            map.put("a", "b");
            map.put("c", "d");
            map.put("k", "l");
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }
        }
    }
    

Map存储自定义对象时如何去重复

import java.util.Objects;

public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

import java.util.HashMap;
public class PersonText {
    public static void main(String[] args) {
        HashMap<Person,String> map = new HashMap<>();
        map.put(new Person("哈哈",18),"渭南");
        map.put(new Person("天天",16),"西安");
        map.put(new Person("解决",15),"重庆");
        map.put(new Person("哈哈",18),"北京");
        System.out.println(map);
    }
}

如果key为自定义类型,去重复的话,重写hashCode和equals方法,去重复过程和set一样,因为set集合的元素到了底层都是保存到了map和key位置上

TreeMap

  1. 概述:TreeMap是Map的实现类
  2. 特点:
    对key进行排序
    无索引
    不能存null
    线程不安全
    key唯一
  3. 数据结构:红黑树
TreeMap() -> 使用其键的自然顺序构造一个新的空树图。
TreeMap(Comparator<? super K> comparator) -> 构造一个新的空树图,根据给定的比较器排序。
    
import java.util.Comparator;
import java.util.TreeMap;
public class PersonText {
    public static void main(String[] args) {
        TreeMap<Person,String> map = new TreeMap(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-(o2.getAge());
            }
        });
        map.put(new Person("hh",16),"a");
        map.put(new Person("jj",19),"k");
        map.put(new Person("gg",12),"c");
        System.out.println(map);
        //[Person{name=gg, age=12}, Person{name=hh, age=16}, Person{name=jj, age=19}]
    }
}

Hashtable集合

  1. 概述:Hashtable是Map的实现类

  2. 特点:
    key唯一,value可重复 -> 如果key重复了,会发生value覆盖
    无序
    无索引
    线程不安全
    不可以存null键null值

  3. 数据结构:哈希表

import java.util.Hashtable;

public class HashTable {
    public static void main(String[] args) {
        Hashtable<String, String> ht = new Hashtable<String, String>();
        ht.put("a", "b");
        ht.put("c", "d");
        ht.put("e", "f");
        ht.put("c", "h");
       // ht.put(null,null);//报错
        System.out.println(ht); //{a=b, e=f, c=h}
    }
}

HashMap和Hashtable区别:

  • 相同点:元素无序、无索引、key唯一

  • 不同点:HashMap线程不安全,Hashtable线程安全

    ​ HashMap可以存储null键null值,Hashtable不可以

Properties集合

  1. 概述:Properties继承Hashtable

  2. 特点:
    key唯一,value可重复 -> 如果key重复了,会发生value覆盖
    无序
    无索引
    线程不安全
    不可以存null键null值
    Properties的key与value默认为String

  3. 数据结构:哈希表

  4. 常用方法:

    Object setProperty(String key, String value) -> 存键值对
    String getProperty(String key) -> 根据key获取value
    Set<String> stringPropertyNames() -> 获取所有的key,保存到set集合中,相当于keySet方法
    void load(InputStream inStream) -> 从输入字节流中读取属性列表(键和元素对)
    
    无序
    无索引
    线程不安全
    不可以存null键null值
    
  5. 数据结构:哈希表

import java.util.Hashtable;

public class HashTable {
    public static void main(String[] args) {
        Hashtable<String, String> ht = new Hashtable<String, String>();
        ht.put("a", "b");
        ht.put("c", "d");
        ht.put("e", "f");
        ht.put("c", "h");
       // ht.put(null,null);//报错
        System.out.println(ht); //{a=b, e=f, c=h}
    }
}

HashMap和Hashtable区别:

  • 相同点:元素无序、无索引、key唯一

  • 不同点:HashMap线程不安全,Hashtable线程安全

    ​ HashMap可以存储null键null值,Hashtable不可以

Properties集合

  1. 概述:Properties继承Hashtable

  2. 特点:
    key唯一,value可重复 -> 如果key重复了,会发生value覆盖
    无序
    无索引
    线程不安全
    不可以存null键null值
    Properties的key与value默认为String

  3. 数据结构:哈希表

  4. 常用方法:

    Object setProperty(String key, String value) -> 存键值对
    String getProperty(String key) -> 根据key获取value
    Set<String> stringPropertyNames() -> 获取所有的key,保存到set集合中,相当于keySet方法
    void load(InputStream inStream) -> 从输入字节流中读取属性列表(键和元素对)
    

总结

  1. List接口:
  • ArrayList:基于动态数组实现,适用于随机访问。插入和删除元素时可能需要数组复制,因此较慢。
  • LinkedList:基于双向链表实现,适用于频繁的插入和删除操作。但是,随机访问速度较慢。
  • Vector:类似于ArrayList,但它是同步的。由于性能问题,通常不推荐使用。
  • 选择:当需要频繁随机访问元素时,选择ArrayList。当需要频繁在列表中间插入或删除元素时,选择LinkedList。
  1. Set接口:
  • HashSet:基于HashMap实现,无序,允许null元素,查找速度快。
  • LinkedHashSet:类似于HashSet,但维护元素的插入顺序。
  • TreeSet:基于NavigableMap实现,可以按照自然顺序或自定义顺序对元素进行排序。
  • 选择:当需要快速查找元素且不需要元素有序时,选择HashSet。当需要维护元素插入顺序时,选择LinkedHashSet。当需要有序集合时,选择TreeSet。
  1. Map接口:
  • HashMap:基于散列表实现,键值对映射,无序,允许一个null键和多个null值。
  • LinkedHashMap:类似于HashMap,但维护键值对的插入顺序。
  • TreeMap:基于红黑树实现,可以按照自然顺序或自定义顺序对键进行排序。
  • Hashtable:类似于HashMap,但它是同步的。由于性能问题,通常不推荐使用。
  • 选择:当需要快速查找键值对且不需要键有序时,选择HashMap。当需要维护键值对的插入顺序时,选择LinkedHashMap。当需要有序的键值对映射时,选择TreeMap。
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值