集合入门说明

java集合

集合的理解和好处

数组的不足之处
  • 长度开始时必须指定,而且一旦指定,不能更改。
  • 保存的必须为同一类型的元素。
  • 使用数组进行增加元素的示意代码比较麻烦。

数组扩容,不灵活,比较麻烦,实例如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.grey.test_01;

import org.junit.jupiter.api.Test;

/**
 * @Description: 数组扩容:灵活性差,比较麻烦
 * @author: lz
 * @since: 2023/8/16
 */
public class ArrayExample {

    @Test
    public void expandArray() {
        Person[] people = new Person[3];

        //添加几个元素进去
        people[0] = new Person("小明", 10);
        people[1] = new Person("小刚", 20);
        people[2] = new Person("小红", 30);

        for (Person person : people) {
            System.out.println(person);
        }

        System.out.println("-----------扩容后----------");

        Person[] peopleAdd = new Person[5];
        for (int i = 0; i < people.length; i++) {
            peopleAdd[i] = people[i];
        }
        peopleAdd[3] = new Person("梅梅", 40);
        peopleAdd[4] = new Person("兰兰", 50);

        for (Person person : peopleAdd) {
            System.out.println(person);
        }

    }
}

class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
集合的好处
  • 可以动态保存任意多个对象,使用比较方便
  • 提供了一系列方便的操作对象的方法:add、remove、set、get等
  • 使用集合添加,删除新元素更加简洁

集合类图

在这里插入图片描述
Collection 接口图

在这里插入图片描述
Map接口图

在这里插入图片描述

1.集合主要是两组(单列集合、双列集合)
2.Collection接口有两个重要的子接口List Set 它们的实现子类都是单列集合
3.Map接口的实现子类 是双列集合,存放的 Key-Value

Collection接口实现类的特点

public interface Collection extends Iterable

  • Collection实现子类可以存放多个元素,每个元素可以是Object
  • 有些Collection的实现类,可以存放重复的元素,有些不可以
  • 有些Collection的实现类是有序的(List),有些是无序的(Set)–这里说的有序和无序是指取出的顺序是否和放入顺序一致
  • Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的

示例:

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;

public class CollectionExp {

    @Test
    @SuppressWarnings("all")
    public void konwCollection() {
        //Collection
        //Map
        //LinkedHashMap
        //ArrayList
        //创建一个ArrayList(单列集合)
        List list = new ArrayList();
        //add添加单个元素
        list.add("hello");
        list.add(10);
        list.add(new Integer(100));
        list.add(true);
        list.add(new Integer(30));
        list.add(new String("word"));
        System.out.println(list);

        //remove删除元素
        list.remove(0);//删除第一个元素hello
        list.remove("word");//指定删除对象
        System.out.println(list);

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

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

        //isEmpty是否为空
        System.out.println(list.isEmpty());

        //clear清空
        list.clear();
        System.out.println(list);

        //addAll可以添加集合,多个元素
        List list2 = new ArrayList();
        list2.add(35.5d);
        list2.add(45.5f);
        list.addAll(list2);
        System.out.println(list);

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

        //removeAll 删除多个元素
        List list3 = new ArrayList();
        list3.add("特别的爱特别的你");
        list.addAll(list3);
        System.out.println("removeAll前:" + list);
        list.removeAll(list3);
        System.out.println("removeAll后:" + list);
    }

}
Collection接口的遍历形式
使用迭代器Iterator(迭代器)
  • Itrator对象称为迭代器,只要用于遍历Collection集合中的元素。
  • 所有实现了Collection接口的集合类都有一个Iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
  • Iterator仅用于遍历集合,Iterator本身并不存放对象

迭代器的执行原理

在这里插入图片描述
Itrator接口的方法

在这里插入图片描述
示例:

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ItratorExercise {

    @Test
    @SuppressWarnings("all")
    public void getItrator() {
        Collection arrayList = new ArrayList();
        arrayList.add(new Book("三国演义", "罗贯中", 42.99));
        arrayList.add(new Book("西游记", "吴承恩", 38.5));
        arrayList.add(new Book("水浒传", "施耐庵", 66.66));

        System.out.println("直接输出:" + arrayList);
        System.out.println("----------------");

        //先得到对应的迭代器
        Iterator iterator = arrayList.iterator();

        while (iterator.hasNext()) { //判断是否还有数据
            //返回下一个元素,类型是Object
            Object next = iterator.next();
            System.out.println(next);
        }

        //当退出while循环后,这时迭代器指向最后一个元素
        //报错 iterator.next(); //java.util.NoSuchElementException

        //如果希望再次遍历,需要重置迭代器
        arrayList.add("今天天气不错");
        System.out.println("重置迭代器之后...........");
        iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }
    }

}

class Book {
    private String name;
    private String author;
    private Double price;

    public Book(String name, String author, Double price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

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

for循环增强遍历

增强for循环,可以替代itrator迭代器,特点:增强for就是简化版的iterator,本质一样。只能用于遍历集合或者数组

基本语法:

for(元素类型 元素名:集合名或数组名){
 访问元素
}

示例:

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;

public class StrongFor {

    @Test
    public void strongFor() {
        ArrayList arrayList = new ArrayList();
        arrayList.add(new Teacher("王老师", 45, 1.68));
        arrayList.add(new Teacher("李老师", 25, 1.58));
        arrayList.add(new Teacher("刘老师", 27, 1.78));

        //使用增强for循环,在Collection集合
        //底层仍然是迭代器
        //增强for循环,可以理解成简化版的迭代器
        for (Object o : arrayList) {
            System.out.println(o);
        }

        //增强for循环也可以在数组中使用
        int[] nums = {1, 8, 9, 10};
        for (int num : nums) {
            System.out.println(num);
        }

    }
}

class Teacher {
    private String name;
    private Integer age;
    private Double height;

    public Teacher(String name, Integer age, Double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Double getHeight() {
        return height;
    }

    public void setHeight(Double height) {
        this.height = height;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                '}';
    }
}
课堂练习:

编写程序CollectionExercise

  • 创建3个Dog{name,age}对象,放入到ArrayList中,赋给List使用
  • 用迭代器和增强for循环两种方式来遍历
  • 重写Dog的toString方法,输出name和age
package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @Description:
 * @author: lz
 * @since: 2023/8/16
 */
public class CollectionExerciseAndIterator {

    @Test
    public void collectionExerciseAndIterator() {
        List list = new ArrayList();
        list.add(new Dog("大黄", 1));
        list.add(new Dog("小贝", 2));
        list.add(new Dog("来福", 3));

        //迭代器
        System.out.println("迭代器");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        System.out.println("增强for循环");
        //增强for循环
        for (Object o : list) {
            System.out.println(o);
        }
    }

}

class Dog {
    private String name;
    private Integer age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

List接口和常用方法

List接口是Collection接口的子接口
  • List集合类中元素有序(即添加顺序和取出顺序一致)、并且可以重复
  • List集合中的每个元素都有其对应的顺序索引,即支持索引
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
  • List接口的常用实现类有:ArrayList、LinkedList和Vector
List接口和常用方法
  • add 在index位置插入元素
  • addAll 从index位置开始将所有元素添加进来
  • get 获取指定index位置的元素
  • indexOf 返回在集合中首次出现的位置
  • lastIndexOf 返回在当前集合中末次出现的位置
  • remove 移除index位置的元素,并返回此元素
  • set 设置指定index位置的元素(替换)
  • subList 返回一个范围位置中的子集合

示例:

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: ListMethod
 * @author: lz
 * @since: 2023/8/17
 */
public class ListMethod {

    @Test
    public void ListMethodExercise() {
        List list = new ArrayList();
        list.add("张三丰");
        list.add("贾宝玉");

        //插入一个元素
        list.add(1, "林黛玉");
        System.out.println(list);

        //插入一个集合
        List list2 = new ArrayList();
        list2.add("Jack");
        list2.add("Tom");
        list.addAll(1, list2);
        System.out.println(list);

        //获取集合中的索引值
        System.out.println("get(2):" + list.get(2));//Tom

        //返回首个出现的位置
        System.out.println(list.indexOf("林黛玉"));//3

        //返回末次出现的位置
        list.add("林黛玉");
        System.out.println(list.lastIndexOf("林黛玉"));//5

        //移除元素并且输出该元素
        list.remove(5);
        System.out.println(list);

        //替换
        list.set(1, "王宝强");
        System.out.println(list);

        //返回范围值内的子集合[0,3)所以只有0,1,2三个元素
        List listReturn = list.subList(0, 3);
        System.out.println(listReturn);
    }
}

练习:

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @Description: ListExercise02
 * @author: lz
 * @since: 2023/8/17
 */
public class ListExercise02 {

    @Test
    @SuppressWarnings("all")
    public void ListExer02() {
        List list = new ArrayList();
        list.add("1 你好");
        list.add("2 hello world");
        list.add("3 10");
        list.add("4 今天天气不错");
        list.add("5 开心");
        list.add("6 难过");
        list.add("7 悲伤");
        list.add("8 喜悦");
        list.add("9 幸福");
        list.add("10 自豪");
        System.out.println(list);

        list.add(1, "韩顺平教育");
        System.out.println("在2号位插入:" + list);
        System.out.println("获取弟5个元素:" + list.get(4));
        list.remove(5);
        System.out.println("删除第5个元素后:" + list);
        list.set(6, "很悲伤");
        System.out.println("修改第7个元素后:" + list);

        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }
    }

}
List的三种遍历方式
  • 方式一:使用迭代器
  • 方式二:增强for循环
  • 方式三:使用普通for循环
package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

/**
 * @Description: Bianli
 * @author: lz
 * @since: 2023/8/17
 */
@SuppressWarnings("all")
public class Bianli {

    @Test
    public void getBianli() {
        List list = new ArrayList();
        list.add("Jack");
        list.add("Tom");
        list.add("鱼香肉丝");
        list.add("北京烤鸭");

        //迭代器遍历
        System.out.println("-----迭代器遍历-----");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        //增强for循环遍历
        System.out.println("-----增强for循环遍历-----");
        for (Object o : list) {
            System.out.println(o);
        }

        //普通for循环遍历(类似数组)
        System.out.println("------普通for循环遍历(类似数组)------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    @Test
    public void getBianLi02() {
        List vector = new Vector();
        vector.add("Jack");
        vector.add("Tom");
        vector.add("鱼香肉丝");
        vector.add("北京烤鸭");

        //迭代器遍历
        System.out.println("-----迭代器遍历-----");
        Iterator iterator = vector.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        //增强for循环遍历
        System.out.println("-----增强for循环遍历-----");
        for (Object o : vector) {
            System.out.println(o);
        }

        //普通for循环遍历(类似数组)
        System.out.println("-----普通for循环遍历(类似数组)-----");
        for (int i = 0; i < vector.size(); i++) {
            System.out.println(vector.get(i));
        }
    }
}
课堂练习2

在这里插入图片描述
冒泡排序排列集合中对象的某个属性

package com.grey.test_01;

import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: ListExercise03
 * @author: lz
 * @since: 2023/8/17
 */
public class ListExercise03 {

    @Test
    public void listExercise03() {
        List list = new ArrayList();
        list.add(new BookTwo("红楼梦", 100.0, "曹雪芹"));
        list.add(new BookTwo("西游记", 10.0, "吴承恩"));
        list.add(new BookTwo("水浒传", 9.0, "施耐庵"));
        list.add(new BookTwo("三国演义", 80.0, "罗贯中"));
        list.add(new BookTwo("西游记", 10.0, "吴承恩"));

        //正常顺序
        System.out.println("-----正常顺序-----");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        //冒泡排序之后的顺序,从小到大
        this.BubbleSort(list);

        //冒泡排序之后
        System.out.println("-----冒泡排序之后-----");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

    private void BubbleSort(List list) {
        int size = list.size();
        for (int i = 0; i < size - 1; i++) {
            for (int j = 0; j < size - i - 1; j++) {
                Object ob1 = list.get(j);
                Object ob2 = list.get(j + 1);
                //向下转型
                BookTwo bookTwo1 = (BookTwo) ob1;
                BookTwo bookTwo2 = (BookTwo) ob2;

                if (bookTwo1.getPrice() > bookTwo2.getPrice()) {
                    list.set(j + 1, bookTwo1);
                    list.set(j, bookTwo2);
                }
            }
        }
    }
}

class BookTwo {
    private String name;
    private Double price;
    private String author;

    public BookTwo(String name, Double price, String author) {
        this.name = name;
        this.price = price;
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

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

ArrayList底层结构和源码分析

  • ArrayList可以放所有的元素甚至是空元素,可以放入多个空值。
  • ArrayList是由数组来实现数据存储的。
  • ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高),在多线程下,不建议用ArrayList。
  • ArrayList中维护了一个Object类型的数组elementData --> transient Object[] elementData --> transient:短暂的,瞬间的,表示该属性不会被序列化
  • 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量是0,第1次添加,则扩容elementData为10,如需再次扩容,则扩容elementData为1.5倍
  • 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍

Vector底层机构和源码剖析

Vector的基本介绍
  • Vector类的定义说明:
    • public class Vector
    • extends AbstractList
    • implements List, RandomAccess, Cloneable,Serializable
  • Vector底层也是一个对象数组,protected Object[] elementData
  • Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized
  • 在开发中,需要线程同步安全时,优先考虑用Vector

Vector和List比较

在这里插入图片描述

LinkedList底层结构

  • LinkedList底层维护了一个双向链表
  • LinkedList中维护了两个属性first和last分别指向首节点和尾节点
  • 每个节点(Node对象),里面又维护了prev,next,item三个属性,其中通过prev指向前一个,通过next指向后一个节点 ,最终实现双向链表。
  • 所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高

在这里插入图片描述

模拟一个双向链表简单示例:

package com.grey.test_02;

import org.junit.jupiter.api.Test;

/**
 * @Description: 模拟一个双向链表
 * @author: lz
 * @since: 2023/8/17
 */
public class LinkedListExercise02 {

    @Test
    public void getLinked() {
        Linked one = new Linked("One");
        Linked two = new Linked("Two");
        Linked four = new Linked("Four");

        one.setNext(two);
        two.setNext(four);

        four.setPre(two);
        two.setPre(one);

        Linked first = one; //定义头结点
        System.out.println("------从头到尾遍历------");
        while (true) {
            if (first == null) {
                break;
            }
            System.out.println(first);
            first = first.getNext();
        }

        Linked last = four; //定义尾结点
        System.out.println("------从尾到头遍历------");
        while (true) {
            if (last == null) {
                break;
            }
            System.out.println(last);
            last = last.getPre();
        }

        //插入一个元素
        Linked three = new Linked("Three");
        two.setNext(three);
        four.setPre(three);

        three.setNext(four);
        three.setPre(two);

        first = one; //定义头结点
        System.out.println("------插入元素3之后,从头到尾遍历------");
        while (true) {
            if (first == null) {
                break;
            }
            System.out.println(first);
            first = first.getNext();
        }

        last = four; //定义尾结点
        System.out.println("------插入元素3之后,从尾到头遍历------");
        while (true) {
            if (last == null) {
                break;
            }
            System.out.println(last);
            last = last.getPre();
        }

    }

}

class Linked {
    private Linked pre;
    private Linked next;
    private Object name;

    public Linked(Object name) {
        this.name = name;
    }

    public Linked getPre() {
        return pre;
    }

    public void setPre(Linked pre) {
        this.pre = pre;
    }

    public Linked getNext() {
        return next;
    }

    public void setNext(Linked next) {
        this.next = next;
    }

    public Object getName() {
        return name;
    }

    public void setName(Object name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Linked{" +
                "name=" + name +
                '}';
    }
}

关于LinkedList源码分析

package com.grey.test_02;

import org.junit.jupiter.api.Test;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * @Description: LinkedList源码分析
 * @author: lz
 * @since: 2023/8/17
 */
public class LinkedListCRUD {

    @Test
    public void linkedListCRUD() {
        LinkedList list = new LinkedList();
        list.add(100);
        list.add(200);
        list.add(300);
        System.out.println(list);

        //修改,把200改成400
        System.out.println(list.set(1, 400));

        //删除400
        System.out.println(list.remove(1));

        //查找第2个元素
        System.out.println(list.get(1));

        //迭代器遍历
        System.out.println("-----迭代器遍历-----");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        System.out.println("增强for循环遍历");
        for (Object o : list) {
            System.out.println(o);
        }

        System.out.println("普通for循环遍历");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
    
}

在这里插入图片描述

Set接口和常用方法

  • 无序(添加和取出的顺序不一致),没有索引
  • 不允许元素重复,所以最多包含一个null
  • JDK API中Set接口的实现类
Set接口的遍历方式

同Collection的遍历方式一样,因为Set接口是Collection接口的子接口。

  • 可以使用迭代器
  • 增强for循环
  • 不能使用索引的方式来获取

常用方法示例:

package com.grey.test_02;

import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * @Description: SetMethod
 * @author: lz
 * @since: 2023/8/17
 */
public class SetMethod {

    @Test
    public void SetMethodEx() {
        //以Set接口的实现类,HashSet为例
        //Set接口的实现类的对象(Set接口对象)不能存放重复元素
        //可以添加一个null
        //Set接口对象存放数据,对象是无序的(添加顺序和取出顺序不一致)
        //取出顺序是固定的
        Set set = new HashSet();
        set.add("小明");
        set.add("小芳");
        set.add("小刚");
        set.add("小明");
        set.add(null);
        set.add(null);
        System.out.println(set);

        //遍历
        //方式1;迭代器
        System.out.println("-----迭代器-----");
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        //增强for循环
        System.out.println("-----增强for循环遍历-----");
        for (Object o : set) {
            System.out.println(o);
        }

        System.out.println("size:" + set.size());
        System.out.println("是否为空:" + set.isEmpty());
        System.out.println("是否包含元素[小刚]:" + set.contains("小刚"));
        System.out.println("remove:" + set.remove("小刚"));
        System.out.println("remove:" + set.remove(null));
        System.out.println(set);
    }

}
HashSet的全面说明
  • HashSet实现了Set接口
  • HashSet实际上是HashMap
  • 可以存放null值,但是只能有一个null
  • HashSet不保证元素是有序的,取决于hash后,再确定索引的结果(不保证元素存放和取出顺序一致)
  • 不能有重复元素/对象。在前面Set接口使用已经讲过了
package com.grey.test_02;

import org.junit.jupiter.api.Test;

/**
 * @Description: HashSetStructure
 * @author: lz
 * @since: 2023/8/17
 */
public class HashSetStructure {

    @Test
    public void getHashSetStr() {
        //模拟一个HashSet的底层(其实就是HashMap)
        //创建一个Node数组,有些人称为table
        Node[] table = new Node[16];
        System.out.println("table:" + table);
        //把john放在2的位置
        Node jhon = new Node("Jhon", null);
        table[2] = jhon;
        System.out.println("table:" + table);

        Node jack = new Node("Jack", null);
        jhon.next = jack; //将jack挂载到jhno后边
        System.out.println("table:" + table);

        //继续把Rose挂载到Jack后面
        Node rose = new Node("Rose", null);
        jack.next = rose;
        System.out.println("table:" + table);

        //把Lucy放到table表索引为3的位置
        Node lucy = new Node("Lucy", null);
        table[3] = lucy;
        System.out.println("table:" + table);
    }

}

//节点,存储数据,可以指向下一个节点
class Node {

    Object item;//存放数据
    Node next;//指向下一个节点

    public Node(Object item, Node next) {
        this.item = item;
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" +
                "item=" + item +
                ", next=" + next +
                '}';
    }
}
HashSet的底层机制

分析:HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)

浓缩成6句话

  • HashSet底层是HashMap
  • 添加一个元素时,先得到hash值,会转成索引值
  • 找到存储数据表table,看这个索引位置是否已经存放的有元素
  • 如果没有,直接加入
  • 如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后
  • 在JAVA 8 中,如果一条链表的元素个数,到达TREEIFY_THRESHOLD(默认是8),并且table的大小>= MIN_TREEIFY_CAPACITY(默认64)就进行树化(红黑树)

在这里插入图片描述

在这里插入图片描述

课堂练习

在这里插入图片描述

课后练习

equals和hashCode示例1:

在这里插入图片描述

package com.grey.test_02;

import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Objects;

/**
 * @Description: Employee
 * @author: lz
 * @since: 2023/8/18
 */
public class Employee {

    @Test
    public void employee() {
        HashSet hashSet = new HashSet();
        hashSet.add(new Workers("小明", 10));
        hashSet.add(new Workers("小红", 20));
        hashSet.add(new Workers("小明", 30));
        hashSet.add(new Workers("小刚", 40));
        hashSet.add(new Workers("小明", 10));
        System.out.println("size:" + hashSet.size());
        System.out.println(hashSet);
    }

}

class Workers {
    String name;
    Integer age;

    public Workers(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

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

    //如果name和age相同,要返回相同的哈希值
    @Override
    public boolean equals(Object obj) {
//        return super.equals(obj);
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Workers workers = (Workers) obj;
        return Objects.equals(name, workers.name) && this.age == workers.age;
    }

    //如果age和name相同,要返回相同的哈希值 (先比较age在比较name)
    /*@Override
    public boolean equals(Object obj) {
//        return super.equals(obj);
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Workers workers = (Workers) obj;
        return this.age == workers.age && Objects.equals(name, workers.name);
    }*/

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

equals和hashCode示例2:重写2次

package com.grey.test_02;

import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Objects;

/**
 * @Description: Employee02
 * @author: lz
 * @since: 2023/8/18
 */
public class Employee02 {

    @Test
    public void getPerson() {
        HashSet hashSet = new HashSet();
        hashSet.add(new Employ("小明", 10000.88d, new MyDate("1996", "01", "01")));
        //姓名一样,出生年份不同
        hashSet.add(new Employ("小明", 10001.88d, new MyDate("1997", "01", "01")));
        //出生年份和工资不同
        hashSet.add(new Employ("小明", 10001.88d, new MyDate("1998", "01", "01")));
        //工资和第一个比不同(按照规则,这个应该不展示)
        hashSet.add(new Employ("小明", 10002.88d, new MyDate("1996", "01", "01")));

        //重写了toString()方法,这里可以遍历一下,看看值
        System.out.println("size:" + hashSet.size());
        for (Object o : hashSet) {
            System.out.println(o);
        }
    }

}

class Employ {
    private String name;
    private double sal;
    private MyDate birthday;

    public Employ(String name, double sal, MyDate birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    @Override
    public boolean equals(Object obj) {
//        return super.equals(obj);
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Employ employ = (Employ) obj;
        return Objects.equals(name, employ.name)
                && Objects.equals(birthday, employ.birthday);
    }

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

    @Override
    public String toString() {
        return "Employ{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}

class MyDate {
    String year;
    String month;
    String day;

    public MyDate(String year, String month, String day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    @Override
    public boolean equals(Object obj) {
//        return super.equals(obj);
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        MyDate myDate = (MyDate) obj;
        return Objects.equals(year, myDate.year)
                && Objects.equals(month, myDate.month) && Objects.equals(day, myDate.day);
    }

    @Override
    public int hashCode() {
        return Objects.hash(year, month, day);
    }

    @Override
    public String toString() {
        return "MyDate{" +
                "year='" + year + '\'' +
                ", month='" + month + '\'' +
                ", day='" + day + '\'' +
                '}';
    }
}

equals和hashCode示例2:重写1次

package com.grey.test_02;

import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Objects;

/**
 * @Description: Employee03
 * @author: lz
 * @since: 2023/8/18
 */
public class Employee03 {

    @Test
    public void getPerson() {
        HashSet hashSet = new HashSet();
        hashSet.add(new Employ02("小明", 10000.88d, new MyDate02("1996", "01", "01")));
        hashSet.add(new Employ02("小明", 10001.88d, new MyDate02("1997", "01", "01")));
        hashSet.add(new Employ02("小明", 10001.88d, new MyDate02("1998", "01", "01")));
        //按照重复数据去重
        hashSet.add(new Employ02("小明", 10002.88d, new MyDate02("1996", "01", "01")));

        System.out.println("size:" + hashSet.size());
        for (Object o : hashSet) {
            System.out.println(o);
        }
    }

}

class Employ02 {
    private String name;
    private double sal;
    private MyDate02 birthday;

    public Employ02(String name, double sal, MyDate02 birthday) {
        this.name = name;
        this.sal = sal;
        this.birthday = birthday;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Employ02 employ02 = (Employ02) obj;
        return Objects.equals(name, employ02.name)
                && Objects.equals(birthday.getYear(), employ02.birthday.getYear())
                && Objects.equals(birthday.getMonth(), employ02.birthday.getMonth())
                && Objects.equals(birthday.getDay(), employ02.birthday.getDay());
    }

    @Override
    public int hashCode() {
        //这里直接重写一次hashCode方法即可
        return Objects.hash(name, birthday.getYear(), birthday.getMonth(), birthday.getDay());
    }

    @Override
    public String toString() {
        return "Employ02{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", birthday=" + birthday +
                '}';
    }
}

class MyDate02 {
    private String year;
    private String month;
    private String day;

    public MyDate02(String year, String month, String day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    public String getMonth() {
        return month;
    }

    public void setMonth(String month) {
        this.month = month;
    }

    public String getDay() {
        return day;
    }

    public void setDay(String day) {
        this.day = day;
    }

    @Override
    public String toString() {
        return "MyDate02{" +
                "year='" + year + '\'' +
                ", month='" + month + '\'' +
                ", day='" + day + '\'' +
                '}';
    }
}
LinkedHashSe

LinkedHashSet的全面说明

  • LinkedHashSet是HashSet的子类
  • LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
  • LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序图(图),这使得元素看起来是以插入顺序保存的。
  • LinkedHashSet不允许添加重复元素

说明:

  1. 在LinkedHashSet中维护一个hash表和双向链表(LinkedHashSet 有head和tail)
  2. 每一个结点有before和after属性,这样可以形成双向链表
  3. 在添加一个元素时,先求hash值,再求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和hashset一样])
    tail.next = newElement
    newElement.pre = tail
    tail = newElement;
  4. 这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致

equals和hashCode重写

package com.grey.test_02;

import org.junit.jupiter.api.Test;

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

/**
 * @Description: 如果name和price一样就认为是一样的元素
 * @author: 多加点冰也没关系
 * @since: 2023/8/18
 */
public class LinkedHashSetExercise01 {

    @Test
    public void getHashSet() {
        LinkedHashSet set = new LinkedHashSet();
        set.add(new Car("奥迪", 1000d));
        set.add(new Car("奥迪", 30000d));
        set.add(new Car("法拉利", 100000d));
        set.add(new Car("保时捷", 7000000d));
        set.add(new Car("奥迪", 1000d));

        for(Object o : set){
            System.out.println(o);
        }
    }
}

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 +
                '}';
    }

    //重写equals和hash方法
    @Override
    public boolean equals(Object obj) {
//        return super.equals(obj);
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Car car = (Car) obj;
        return Double.compare(car.price, price) == 0 && Objects.equals(name, car.name);
    }

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

Map集合

Map接口实现类的特点
  • Map与Collection并列存在,用于保存具有映射关系的数据Key-Value(双列元素)
  • Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  • Map中的key不允许重复,原因和HashSet一样,前面分析过源码。
  • Map中的value可以重复
  • Map的key可以为null,value也可以为null,注意key为null,只能有一个,value为null可以多个
  • 常用String类作为Map的key
  • key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
  • Map存放数据的key-value示意图,一对key-value 是放在一个Node中的,又因为Node实现了Entry接口,有些书上也说一对key-value就是一个Entry(如图)
package com.grey.test_03;

import org.junit.jupiter.api.Test;

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

/**
 * @Description: MapExercise
 * @author: 多加点冰也没关系
 * @since: 2023/8/18
 */
public class MapExercise {

    @Test
    public void getExercise() {
        //Map接口具有的特点
        //常用String类作为Map的key
        Map hashMap = new HashMap();
        hashMap.put("1", "Jack");
        hashMap.put("2", 10);
        hashMap.put("3", "贾斯汀比伯");
        hashMap.put("4", "迈克尔杰克逊");
        hashMap.put("5", "贾斯汀比伯");
        hashMap.put("6", "Alice");
        hashMap.put("7", "VERTGA");
        hashMap.put("8", "LAM");
        hashMap.put("9", "GIN");
        hashMap.put("10", "TIO");
        hashMap.put("11", "AIO");
        hashMap.put("12", "Tony");
        hashMap.put("13", "Joy");

        //替换机制:当有相同key值时,就替换
        hashMap.put("1", "Rose");
        hashMap.put(null, null);

        //Map的key可以为null,value也可以为null,
        //注意:key为null,只能有一个,value为null可以有多个
        hashMap.put(null, null);
        hashMap.put("17", null);

        //替换
        hashMap.put(null, 181);

        //key可以用别的类型
        hashMap.put(1, "Jack");

        System.out.println(hashMap);
        System.out.println("get(1):" + hashMap.get(1));
    }
}

entrySet()获取entrySet
entrySet是一个Set<Entry<key,value>接口,里面存放的是Entry对象,Entry对象里面存放的是key的引用和value的引用

Map的常用方法
  • put:添加
  • remove:根据键删除映射关系
  • get:根据键获取值
  • size:获取元素个数
  • isEmpty:判断个数是否为0
  • clear:清除
  • containsKey:查找键是否存在
package com.grey.test_03;

import org.junit.jupiter.api.Test;

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

/**
 * @Description: MapUse
 * @author: 多加点冰也没关系
 * @since: 2023/8/18
 */
public class MapUse {

    @Test
    public void mapUse() {
        /**
         * (1)put:添加
         * (2)remove:根据键删除映射关系
         * (3)get:根据键获取值
         * (4)size:获取元素个数
         * (5)isEmpty:判断个数是否为0
         * (6)clear:清除
         * (7)containsKey:查找键是否存在
         */

        Map map = new HashMap();
        map.put("1", "Book");
        map.put("邓超", "孙俪");
        map.put("马蓉", "王宝强");
        map.put("马蓉", "宋喆");

        System.out.println(map);

        map.remove("1");
        System.out.println(map);

        System.out.println(map.get("邓超"));

        System.out.println("size:" + map.size());

        System.out.println("是否为空:" + map.isEmpty());

        System.out.println("有没有马蓉:" + map.containsKey("马蓉"));

        map.clear();
        System.out.println("clear之后:" + map);
    }
}
Map接口遍历方法

Map遍历的示意图(比List,和Set复杂一点,但是基本原理一样)

  • containsKey:查找键是否存在
  • keySet:获取所有的键
  • entrySet:获取所有关系
  • values:获取所有的值
package com.grey.test_03;

import org.junit.jupiter.api.Test;

import java.util.*;

/**
 * @Description: MapBl
 * @author: lz
 * @since: 2023/8/18
 */
public class MapBl {

    @Test
    public void MapBl() {
        Map map = new HashMap();
        map.put("1", "Jack");
        map.put("上单", "老夫子");
        map.put("中单", "诸葛亮");
        map.put("射手", "后裔");
        System.out.println(map);

        //遍历(自己想的)
        System.out.println("----增强for循环----");
        Set set = map.entrySet();
        for (Object o : set) {
            System.out.println(o);
        }

        //遍历(自己想的)
        System.out.println("----迭代器----");
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }

        //韩老师讲的
        //1.先取出所有的key,通过key找到对应的value
        System.out.println("-----map.keySet()-----");
        Set keySet = map.keySet();
        for (Object o : keySet) {
            //向下转型
            System.out.println("key = " + o + "  value = " + map.get(0));
        }

        //2.通过迭代器
        System.out.println("----map.keySet()的迭代器----");
        Iterator iterator1 = keySet.iterator();
        while (iterator1.hasNext()) {
            Object next = iterator1.next();
            System.out.println("key = " + next + "   value = " + map.get(next));
        }

        //3.只是把所有的values取出
        System.out.println("----map.values()----");
        Collection values = map.values();
        for (Object value : values) {
            System.out.println("value = " + value);
        }

        System.out.println("----map.values()迭代器----");
        Iterator iterator2 = values.iterator();
        while (iterator2.hasNext()) {
            Object next = iterator2.next();
            System.out.println("value = " + next);
        }

        //3.通过EntrySet
        //增强for循环
        System.out.println("----map.entrySet()增强for循环----");
        Set entrySet = map.entrySet();
        for (Object o : entrySet) {
            Map.Entry entry = (Map.Entry) o;
            System.out.println("key = " + entry.getKey() + "value = " + entry.getValue());
        }

        //通过迭代器
        System.out.println("----entrySet迭代器----");
        Set entrySet2 = map.entrySet();
        Iterator iterator3 = entrySet2.iterator();
        while (iterator3.hasNext()) {
            Object next = iterator3.next();
//            System.out.println(next.getClass());//HashMap$Node
            Map.Entry entry = (Map.Entry) next;
            System.out.println("key = " + entry.getKey() + "   value = " + entry.getValue());
        }
    }
}
课后练习

在这里插入图片描述

package com.grey.test_03;

import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Description: AfterClassExercise
 * @author: 多加点冰也没关系
 * @since: 2023/8/18
 */
public class AfterClassExercise {

    @Test
    public void showWorkers() {
        /*HashSet hashSet = new HashSet();
        hashSet.add(new Workers("王晓亮", 15000.5, "no.1"));
        hashSet.add(new Workers("钟飞扬", 16060.5, "no.2"));
        hashSet.add(new Workers("潘长江", 18060.5, "no.3"));
        hashSet.add(new Workers("小悦悦", 27060.5, "no.4"));
        System.out.println(hashSet);

        for (Object o : hashSet) {
            Map.Entry entry = (Map.Entry) o;
            entry.getKey();
        }*/

        HashMap hashMap = new HashMap();
        hashMap.put("no.1", new Workers("王晓亮", 15000.5, "no.1"));
        hashMap.put("no.2", new Workers("钟飞扬", 16060.5, "no.2"));
        hashMap.put("no.3", new Workers("潘长江", 18060.5, "no.3"));
        hashMap.put("no.4", new Workers("小悦悦", 27060.5, "no.4"));
        hashMap.put("no.5", "Jack");

        //显示工资大于18000的人
        System.out.println("--------keySet()--------");
        Set set = hashMap.keySet();
        for (Object o : set) { //String
            //System.out.println(o.getClass());
            //instanceof 作用是:测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
            if (hashMap.get(o) instanceof Workers) {
                //hashMap.get(o)是对象Workers
                Workers workers = (Workers) hashMap.get(o);
                if (workers.getSal() > 18000) {
                    System.out.println("key = " + o + "   value = " + hashMap.get(o));
                }
            } else {
                System.out.println("key = " + o + "   value = " + hashMap.get(o));
            }
        }

        //迭代器
        System.out.println("-----------------keySet()迭代器------------------");
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            if (hashMap.get(next) instanceof Workers) {
                Workers workers = (Workers) hashMap.get(next);
                if (workers.getSal() > 18000) {
                    System.out.println("key = " + next + "  value = " + hashMap.get(next));
                }
            } else {
                System.out.println("key = " + next + "  value = " + hashMap.get(next));
            }
        }

        //使用entrySet()方法
        System.out.println("-----------entrySet()增强for循环-----------");
        Set set1 = hashMap.entrySet();
        for (Object o : set1) {
            Map.Entry entry = (Map.Entry) o;
            if (entry.getValue() instanceof Workers) {
                Workers workers = (Workers) entry.getValue();
                if (workers.getSal() > 18000) {
                    System.out.println("key = " + entry.getKey() + "   value = " + entry.getValue());
                }
            } else {
                System.out.println("key = " + entry.getKey() + "   value = " + entry.getValue());
            }
        }
    }

}

class Workers {
    private String id;
    private String name;
    private Double sal;

    public Workers(String name, Double sal, String id) {
        this.id = id;
        this.name = name;
        this.sal = sal;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getSal() {
        return sal;
    }

    public void setSal(Double sal) {
        this.sal = sal;
    }

    @Override
    public String toString() {
        return "Workers{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", sal=" + sal +
                '}';
    }
}
HashMap小结
  • Map接口的常用实现类:HashMap、Hashtable和Properties
  • HashMap是Map接口使用频率最高的实现类
  • HashMap是以key-value 对的方式来存储数据(HashMap$Node类型)
  • key不能重复,但是值可以重复,允许使用null值和null键(null键只能有1个)
  • 如果添加相同的key,则会覆盖原来的key-val,等同于修改(key不会替换,val会替换)
  • 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的。
  • HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized
HashMap底层机制以及源码剖析
  • HashMap底层维护了Node类型的数组table,默认为null
  • 当创建对象时,将加载因子(loadFactor)初始化为0.75
  • 当添加key-value时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素,则直接添加。如果该处索引有元素,则继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换成新的val,如果不相等,需要判断是树结构还是链表结构,做出相应的处理。如果添加时发现容量不够,则需要扩容。
  • 第1次添加,则需要扩容table容量为16,临界值(threshold)为12
  • 以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,以此类推。
  • 在Java8中,如果一条链表的元素个数超过了TREEIFY_THRESHOLD(默认是8),并且table的大小>= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)
模拟HashMap触发扩容、树化情况
package com.grey.test_03;

import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Objects;
import java.util.Set;

/**
 * @Description: HashMapSource
 * @author: 多加点冰也没关系
 * @since: 2023/8/18
 */
public class HashMapSource {

    @Test
    public void getSource() {
        HashMap hashMap = new HashMap();
//        HashSet hashSet = new HashSet();
//        LinkedHashSet linkedHashSet = new LinkedHashSet();
        hashMap.put(new Cat("小红", 1), "no1.Jack");
        hashMap.put(new Cat("小红", 2), "no2.Jack");
        hashMap.put(new Cat("小红", 3), "no3.Jack");
        hashMap.put(new Cat("小红", 4), "no4.Jack");
        hashMap.put(new Cat("小红", 5), "no5.Jack");
        hashMap.put(new Cat("小红", 6), "no6.Jack");
        hashMap.put(new Cat("小红", 7), "no7.Jack");
        hashMap.put(new Cat("小红", 8), "no8.Jack");

        /**
         * // 从第二次put之后才会进这里,并且第二次循环时 var12 0  第二次循环结束 var12 1 -- 即第三次循环开始 var12 1
         *    所以var12比put的次数少2,一直到put第9的时候,var12 >= 7才会满足
         *                 while(true) {
         *                     if ((var10 = ((HashMap.Node)var7).next) == null) {
         *                         ((HashMap.Node)var7).next = this.newNode(var1, var2, var3, (HashMap.Node)null);
         *                         if (var12 >= 7) {
         *                             this.treeifyBin(var6, var1);
         *                         }
         *                         break;
         *                     }
         *
         *                     if (((HashMap.Node)var10).hash == var1 && ((var11 = ((HashMap.Node)var10).key) == var2 || var2 != null && var2.equals(var11))) {
         *                         break;
         *                     }
         *
         *                     var7 = var10;
         *                     ++var12;
         *                 }
         */

        hashMap.put(new Cat("小红", 9), "no9.Jack");
        hashMap.put(new Cat("小红", 10), "no10.Jack");
        hashMap.put(new Cat("小红", 11), "no11.Jack");
        hashMap.put(new Cat("小红", 12), "no12.Jack");

        /**
         * if (++this.size > this.threshold) { 所以是第13次put的时候扩容 16 → 32
         *             this.resize();
         *         }
         */

        hashMap.put(new Cat("小红", 13), "no13.Jack"); //
        hashMap.put(new Cat("小红", 14), "no14.Jack");

        hashMap.put(new Cat("小蓝", 9), "no9.Jack"); // 扩容table 32
        hashMap.put(new Cat("小蓝", 10), "no10.Jack"); // 扩容table 64
        hashMap.put(new Cat("小蓝", 11), "no11.Jack"); // 将链表转换成红黑树

        //hashMap.put("11", "no111.Jack");
        //hashMap.put("12", "no12.Jack");
        //hashMap.put("13", "no13.Jack"); // 超过12才扩容
/*        hashMap.remove(new Cat("小蓝", 11));
        hashMap.remove(new Cat("小蓝", 10));
        hashMap.remove(new Cat("小蓝", 9));
        hashMap.remove(new Cat("小红", 8));
        hashMap.remove(new Cat("小红", 7));
        hashMap.remove(new Cat("小红", 6));
        hashMap.remove(new Cat("小红", 5));
        hashMap.remove(new Cat("小红", 4)); // 执行完之后剪枝
        hashMap.remove(new Cat("小红", 3));
        hashMap.remove(new Cat("小红", 3));*/

        Set set = hashMap.keySet();
        for (Object o : set) {
            System.out.println("key = " + o + " value = " + hashMap.get(o));
        }
        System.out.println(hashMap);
    }

}

class Cat {
    private String name;
    private Integer age;

    public Cat(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

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

    @Override
    public int hashCode() {
        return Objects.hash(100);
    }
}
Map接口实现类-Hashtable
  • 存放的元素是键值对:即K-V
  • hashtable的键和值都不能为null,否则会抛出NullPointerException
  • hashTable使用方法基本上和HashMap一样
  • hashTable是线程安全的(synchronized),hashMap是线程不安全的
  • 实现Map接口

注意:

  1. 底层有数组 Hashtable$Entry[] 初始化大小为11
  2. 临界值 threshold = 11 * 0.75 ≈ 8
  3. 扩容:按照自己的扩容机制来进行
  4. 执行方法 addEntry(hash, key, value, index); 添加键值对,封装到Entry
Hashtable和HashMap对比
名称版本线程安全(同步)效率允许null键null值
Hashtable1.2不安全可以
HashMap1.0安全较低不可以

Properties

基本介绍

  • Properties类继承自Hashtable类并且实现了Map接口,也是一种键值对的形式来保存数据。
  • 它的使用特点和Hashtable类似。
  • Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改。
  • 说明:工作后xxx.properties文件通常作为配置文件,这个知识点在IO流举例,有兴趣可先看文章。

配置文件不会显示乱码,统一调整为UTF-8

在这里插入图片描述

package com.Map.Properties;
	
import org.junit.Test;
	
import java.io.*;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class PropertiesEx {
    @Test
    public void propertiesEx() {
        Properties properties = new Properties();

        String path = "src/com/Map/File/res.properties";

        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(path));
            properties.load(bufferedReader);
            Set<Map.Entry<Object, Object>> entries = properties.entrySet();
            Iterator<Map.Entry<Object, Object>> iterator = entries.iterator();
            while (iterator.hasNext()) {
                Map.Entry<Object, Object> next = iterator.next();
                System.out.println("key = " + next.getKey() + " value = " + next.getValue());
            }

            // 写入
            bufferedWriter = new BufferedWriter(new FileWriter(path));
            properties.setProperty("signature", "rose");
            properties.setProperty("signature", "厉害");
            properties.store(bufferedWriter, "This is my destney哈哈");


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
                bufferedWriter.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

res.properties

name=root
key=value
pass=liu

基本用法

package com.Map.Properties;

import org.junit.Test;

import java.util.Properties;

public class PropertiesExercise {
    @Test
    public void getEx() {
        Properties properties = new Properties();
        properties.put("no.1", "Jack");
        properties.put("no.2", "Jone");
        // 有相同的key,value会被替换
        properties.put("no.2", "Joy");
        //properties.put(null,null); // java.lang.NullPointerException
        // 键不能为空
        //properties.put(null,"1"); // java.lang.NullPointerException
        // 值不能为空
        //properties.put("no.3",null); // java.lang.NullPointerException

        properties.put("no.3", "Rose");


        System.out.println(properties);

        // 通过key获取对应的值
        System.out.println("no.2:  " + properties.get("no.2"));

        properties.remove("no.3");
        System.out.println("删除no.3之后");
        System.out.println(properties);


        // 修改:
        properties.setProperty("no.2", "Alice");
        System.out.println("setProperty修改no.2之后");
        System.out.println(properties);

        properties.put("no.2", "Rice");
        System.out.println("putno.2之后");
        System.out.println(properties);

        // 查找
        System.out.println("getProperty no.1之后");
        System.out.println(properties.getProperty("no.1"));
    }
}

集合选型

在开发中,选择什么集合实现类,主要取决于业务操作特点,然后根据集合实现类特性进行选择,分析如下:

(1)先判断存储类型(一组对象(单列)或者键值对(双列))  
(2)一组对象: Collection接口  
   允许重复:List  
            增删多:LinkedList(底层是双向链表)  
            查改多:ArrayList(底层维护Object类型的可变数组)  
  不允许重复:Set
            无序:HashSet底层是HashMap,维护一个Hash(数组+链表+红黑树)  
			排序:TreeSet  
            插入和取出顺序一样: LinkedHashSet(继承自LinkedHashMap),维护数组+双向链表  
(3)键值对:Map
         键无序:HashMap(底层是:哈希表:数组+链表+红黑树)  
		 键有序:TreeMap  
         键插入和取出顺序一致:LinkedHashMap(继承自HashMap)  
 		 读取文件: Properties  

TreeSet

TreeSet含Comparator构造器

package com.SetExercise;

import org.junit.Test;

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

public class TreeSetExercise {
    @Test
    @SuppressWarnings({"all"})
    public void getTreeSet() {
        // 当使用无参构造器创建TreeSet的时候是无序的
        TreeSet treeSet = new TreeSet();
        // 添加数据
        treeSet.add("Derrick");
        treeSet.add("Rose");
        treeSet.add("Jam");
        treeSet.add("Timmy");
        treeSet.add("Tom");

        System.out.println(treeSet);


        System.out.println("---字符串按照首字母顺序比较---");
        // 添加的元素按照字符串大小来排序
        // 可以传入一个比较器(匿名内部类),并指定规则
        TreeSet treeSet1 = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o, Object t1) {
                return ((String) o).compareTo((String) t1);
            }
        });
        treeSet1.add("Derrick");
        treeSet1.add("Rose");
        treeSet1.add("Jam");
        treeSet1.add("Timmy");
        treeSet1.add("Tom");

        System.out.println(treeSet1);
        // 源码解读
        /**
         *     public TreeMap(Comparator<? super K> var1) {
         *         this.comparator = var1; 把new Comparator() 给到TreeMap的comparator属性
         *     }
         */

        System.out.println("---字符串长度大小比较---");
        TreeSet treeSet2 = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o, Object t1) {
                String str_a = (String) o;
                String str_t1 = (String) t1;
                int a = ((String) o).length();
                int b = ((String) t1).length();
                int result = a - b;
                return result = result == 0 ? str_a.compareTo(str_t1) : result;
            }
        });
        treeSet2.add("Derrick");
        treeSet2.add("Amy");
        treeSet2.add("Rose");
        treeSet2.add("Jam"); // 相同长度加不进去
        treeSet2.add("Timmy");
        treeSet2.add("Tom");// 相同长度加不进去


        System.out.println(treeSet2);


    }
}
TreeMap
package com.Map;

import org.junit.Test;

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

public class TreeMapExercise {
    @Test
    public void getTreeMap() {
        // 无参数,无序取出
        TreeMap treeMap = new TreeMap();
        treeMap.put("1", "Jack");
        treeMap.put("no2", "Tom");
        treeMap.put("李小璐", "PGONE");
        treeMap.put("smith", "史密斯");

        System.out.println(treeMap);

        // 按照key字符串首字母倒叙排序
        TreeMap treeMap2 = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String) o2).compareTo((String) o1);
            }
        });
        System.out.println("按照key字符串首字母倒叙排序");
        treeMap2.put("1", "Jack");
        treeMap2.put("no2", "Tom");
        treeMap2.put("李小璐", "PGONE");
        treeMap2.put("smith", "史密斯");
        treeMap2.put("alice", "漫游记");
        System.out.println(treeMap2);

        // 按照key字符串长度排序,相同长度按首字母倒叙排序
        TreeMap treeMap3 = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String str_o1 = (String) o1;
                String str_o2 = (String) o2;

                int a = str_o1.length();
                int b = str_o2.length();

                int result = a == b ? str_o1.compareTo(str_o2) : a - b;

                return result;
            }
        });
        System.out.println("按照key字符串长度排序,相同长度按首字母顺叙排序");
        treeMap3.put("1", "Jack");
        treeMap3.put("no2", "Tom");
        treeMap3.put("李小璐", "PGONE");
        treeMap3.put("smith", "史密斯");
        treeMap3.put("alice", "漫游记");
        treeMap3.put("tonny", "理发师");
        System.out.println(treeMap3);
    }
}

Collections工具类

Collections工具类介绍

  • Collections是一个操作Set、List和Map等集合的工具类
  • Collections中提供了一系列静态的方法对集合元素进行排序、查询和修改操作
排序操作(均为static方法)
  • reverse(List):反转List中元素的顺序
  • shuffle(List):对List集合元素进行随机排序
  • sort(List):根据元素的自然顺序对指定List集合元素按升序排序
  • sort(List,Comparator):根据指定的Comparator产生的顺序对List集合进行排序
  • swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
package com.CollectionsUse;

import org.junit.Test;

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

public class CollectionsUse {
    @Test
    public void getUse() {
        HashMap hashMap = new HashMap();
        hashMap.put("Jack", "Rose");
        hashMap.put("no.1", "Tony");
        hashMap.put("no.2", "Jancy");
        hashMap.put("This", "is my destney");

        /**
         * (1)reverse(List):反转List中元素的顺序
         * (2)shuffle(List):对List集合元素进行随机排序
         * (3)sort(List):根据元素的自然顺序对指定List集合元素按升序排序
         * (4)sort(List,Comparator):根据指定的Comparator产生的顺序对List集合进行排序
         * (5)swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
         */
        System.out.println(hashMap);


        ArrayList arrayList = new ArrayList();
        arrayList.add("Derrick");
        arrayList.add("Rose");
        arrayList.add("no.1");
        arrayList.add("2");
        arrayList.add("周润发");
        arrayList.add("周杰伦");
        arrayList.add("洪辰");
        System.out.println("----正常-----");
        System.out.println(arrayList);

        Collections.reverse(arrayList); // (1)reverse(List):反转List中元素的顺序
        System.out.println("----倒叙----");
        System.out.println(arrayList);

        System.out.println("----随机顺序----");
        Collections.shuffle(arrayList); // (2)shuffle(List):对List集合元素进行随机排序
        System.out.println(arrayList);


        System.out.println("----再次随机顺序----");
        Collections.shuffle(arrayList);
        System.out.println(arrayList);

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


        // sort(List,Comparator):根据指定的Comparator产生的顺序对List集合进行排序
        System.out.println("----自然排序Comparator:按照字符串长度大小排序----");
        Collections.sort(arrayList, new Comparator() {

            @Override
            public int compare(Object o1, Object o2) {

                if (o1 instanceof String && o2 instanceof String) {

                    String str_o1 = (String) o1;
                    String str_o2 = (String) o2;

                    int a = str_o1.length();
                    int b = str_o2.length();

                    int result = a == b ? str_o1.compareTo(str_o2) : a - b;
                    return result;
                } else {
                    return 0;
                }
            }
        });
        System.out.println(arrayList);

        // (5)swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
        System.out.println("----交换第一个和第三个元素----");
        Collections.swap(arrayList, 0, 2);
        System.out.println(arrayList);

    }
}
查找和替换
  • Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
  • Object max(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最大元素
  • Object min(Collection)
  • Object min(Collection, Object)
  • int frequency(Collection, Object):返回指定集合中指定元素的出现次数
  • void copy(List dest, List src):将src中的内容复制到dest中
  • boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值
@Test
public void getUseCollections() {

    /**
     * (1)reverse(List):反转List中元素的顺序
     * (2)shuffle(List):对List集合元素进行随机排序
     * (3)sort(List):根据元素的自然顺序对指定List集合元素按升序排序
     * (4)sort(List,Comparator):根据指定的Comparator产生的顺序对List集合进行排序
     * (5)swap(List,int,int):将指定list集合中的i处元素和j处元素进行交换
     */


    ArrayList arrayList = new ArrayList();
    arrayList.add("Derrick");
    arrayList.add("Rose");
    arrayList.add("no.1");
    arrayList.add("2");
    arrayList.add("周润发");
    arrayList.add("周杰伦");
    arrayList.add("洪辰");
    arrayList.add("Rose");
    System.out.println("----正常-----");
    System.out.println(arrayList);

    /**
     * (1)Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
     * (2)Object max(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最大元素
     * (3)Object min(Collection)
     * (4)Object min(Collection, Object)
     * (5)int frequency(Collection, Object):返回指定集合中指定元素的出现次数
     * (6)void copy(List dest, List src):将src中的内容复制到dest中
     * (7)boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值
     */

    // (1)Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
    System.out.println("Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素");
    System.out.println(Collections.max(arrayList));

    // Object max(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最大元素
    System.out.println("Object max(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最大元素  ");
    System.out.println(Collections.max(arrayList, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {

            if (o1 instanceof String && o2 instanceof String) {

                String str_o1 = (String) o1;
                String str_o2 = (String) o2;

                int a = str_o1.length();
                int b = str_o2.length();

                int result = a == b ? str_o1.compareTo(str_o2) : a - b;
                return result;
            } else {
                return 0;
            }
        }
    }));


    // (3)Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
    System.out.println("Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素");
    System.out.println(Collections.min(arrayList));


    // Object max(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最大元素
    System.out.println("Object min(Collection, Comparator):根据Compartor指定的顺序,返回给定集合中的最小元素  ");
    System.out.println(Collections.min(arrayList, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {

            if (o1 instanceof String && o2 instanceof String) {

                String str_o1 = (String) o1;
                String str_o2 = (String) o2;

                int a = str_o1.length();
                int b = str_o2.length();

                int result = a == b ? str_o1.compareTo(str_o2) : a - b;
                return result;
            } else {
                return 0;
            }
        }
    }));

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


    // void copy(List dest, List src):将src中的内容复制到dest中
    // 拷贝要注意 ,拷贝后的集合dest的元素个数要>=被拷贝集合arrayList
    // 一般情况在初始化dest指定大小和arrayList相同
    //ArrayList dest = new ArrayList(); // java.lang.IndexOutOfBoundsException
    ArrayList dest = new ArrayList();
    for (int i = 0; i < arrayList.size(); i++) {
        dest.add(i);
    }
    dest.add("Copy");
    dest.add("Paste");
    Collections.copy(dest, arrayList);
    System.out.println("dest集合元素:");
    System.out.println(dest);

    ArrayList arrayList1 = new ArrayList(10); // 指的是容量(达到后下次扩容成当前的1.5倍)
    System.out.println("arrayList1.size(): " + arrayList1.size());

    //boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值
    System.out.println("boolean replaceAll(List list, Object oldVal, Object newVal):使用新值替换List对象的所有旧值  ");
    Collections.replaceAll(dest, "周润发", "金喜善"); // 如果有周润发就替换成金喜善
    System.out.println(dest);

}

课后作业

课后作业1:

在这里插入图片描述

package com.HomeWork;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class HomeWork01 {
    @Test
    public void HomeWork() {
        ArrayList arrayList = new ArrayList();
        arrayList.add(new News("新闻一:新冠确诊病例超过千万,数以万计印度教徒赶赴恒河"));
        arrayList.add(new News("新闻二:男子突然想起2个月前钓的鱼还在网兜"));
        System.out.println("----倒序遍历----");
        Collections.reverse(arrayList);
        for (Object o : arrayList) {
            // 先实例化对象
            News news = (News) o;

            if (news.getTitle().length() > 15) {
                System.out.println(news.getTitle().substring(0, 15) + "…………");
            } else {
                System.out.println(news.getTitle());
            }
        }
    }

    @Test
    public void HomeWork01_Teacher() {
        ArrayList arrayList = new ArrayList();
        arrayList.add(new News("新闻一:新冠确诊病例超过千万,数以万计印度教徒赶赴恒河"));
        arrayList.add(new News("新闻二:男子突然想起2个月前钓的鱼还在网兜"));
        System.out.println("----倒序遍历----");

        for (int i = arrayList.size() - 1; i >= 0; i--) {
            News news = (News) arrayList.get(i);
            System.out.println(substrTitle(news.getTitle()));
        }
    }

    public String substrTitle(String title) {
        if (null == title || "".equals(title)) {
            return "";
        }

        if (title.length() > 15) {
            return title.substring(0, 15) + "…………";
        } else {
            return title;
        }
    }
}

class News {
    private String title;
    private String text;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    @Override
    public String toString() {
        return "News{" +
                "title='" + title + '\'' +
                '}';
    }

    public News(String title) {
        this.title = title;
    }
}
课后习题2

在这里插入图片描述

package com.HomeWork;

import org.junit.Test;

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

public class HomeWork02 {
    @Test
    public void getHomeWork02() {
        List list = new ArrayList();
        Car car1 = new Car("宝马", 400000);
        Car car2 = new Car("宾利", 5000000);
        Car car3 = new Car("劳斯莱斯", 60000000);
        Car car4 = new Car("法拉利", 70000000);
        list.add(car1);
        list.add(car2);
        System.out.println(list);

        list.remove(car1);
        System.out.println(list);

        System.out.println(list.contains(car2));

        System.out.println(list.size());
        System.out.println(list.isEmpty());
        list.clear();
        System.out.println(list);

        List list2 = new ArrayList();
        list2.add(car1);
        list2.add(car2);
        list2.add(car3);
        list2.add(car4);
        list.addAll(list2);
        System.out.println("----list.addAll(list2)----");
        System.out.println(list);


        System.out.println(list2.containsAll(list));
        list2.removeAll(list);
        System.out.println(list2);

        System.out.println("list增强for循环");

        for (Object o : list) {
            System.out.println(o);
        }

        System.out.println("list迭代器");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println(next);
        }


    }
}

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 +
                '}';
    }
}
课后习题3

在这里插入图片描述

package com.HomeWork;

import org.junit.Test;

import java.util.*;

public class HomeWork03 {
    @Test
    public void getHomeWork03() {
        Map map = new HashMap();
        map.put("1", new Worker("jack", 650));
        map.put("2", new Worker("tom", 1200));
        map.put("3", new Worker("smith", 2900));

        System.out.println("正常情况");
        Set set = map.keySet();
        for (Object o : set) {
            Worker worker = (Worker) map.get(o);
            System.out.println(worker);
        }

        // jack更改为2600元
        System.out.println("----更改工资和加薪后----");
        map.put("1", new Worker("jack", 2600));
        System.out.println(map);
        // 为所有员工加薪100元
        Set set1 = map.entrySet();
        Iterator iterator = set1.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();

            Map.Entry entry = (Map.Entry) next;

            Worker worker = (Worker) entry.getValue();

            // 加薪
            worker.setSal(worker.getSal() + 100);
            //System.out.println(worker.getSal() + 100);

            System.out.println(worker);

        }

        System.out.println("----遍历工资----");
        // 把工资遍历出来
        Collection values = map.values();
        for (Object value : values) {
            Worker worker = (Worker) value;
            System.out.println(worker.getSal());
        }
    }
}

class Worker {
    private String name;
    private double sal;

    public Worker(String name, double sal) {
        this.name = name;
        this.sal = sal;
    }

    @Override
    public String toString() {
        return name + "————" + sal + "元";
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }
}
简答题

试分析HashSet和TreeSet分别是如何实现去重的

  • HashSet的去重机制:hashCode() + equals(),底层先通过存入对象,进行运算得到一个hash值,通过hash值得到对应的索引,如果发现table索引所在的位置,没有数据,就直接存放,如果有数据,就进行equals比较[遍历比较],如果比较后不相同就加入,否则就不加入。
  • TreeSet的去重机制:如果你传入了一个Comparator匿名对象,就使用实现的compare去重,如果方法返回0,就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Comparator接口的compareTo去重。
课后作业5:
package com.HomeWork;

import org.junit.Test;

import java.util.TreeMap;
import java.util.TreeSet;

public class HomeWork05 {
    @Test
    public void getHomeWorker05() {
        TreeSet treeSet = new TreeSet();
        treeSet.add(new Person()); // java.lang.ClassCastException 报错
        // 错误原因:treeSet在add时候会执行
        /**
         *     final int compare(Object var1, Object var2) {
         *         return this.comparator == null ? ((Comparable)var1).compareTo(var2) : this.comparator.compare(var1, var2);
         *     }
         *
         *     会把加入的元素var1 转换成(Comparable) 对象,所以Person必须实现Comparable接口才行
         */
    }
}

class Person implements Comparable { // 实现之后再添加就不会报错了
    /**
     *TreeSet的去重机制:如果你传入了一个Comparator匿名对象,就使用实现的compare去重,如果方法返回  	0,就认为是相同的元素/数据,就不添加,如果你没有传入一个Comparator匿名对象,则以你添加的对象实现的Comparator接口的compareTo去重。
     *     final int compare(Object var1, Object var2) {
     *         return this.comparator == null ? ((Comparable)var1).compareTo(var2) : this.comparator.compare(var1, var2);
     *     }
     * @param o
     * @return
     */
    @Override
    public int compareTo(Object o) {
        return 0;
    }
}
课后作业6

Vector和ArrayList比较

           底层结构      版本   线程安全(同步)效率    扩容倍数
ArrayList  可变数组      1.2    线程不安全,效率高   无参第一次扩容至10,从第二次开始按照1.5倍扩容

Vector     可变数组      1.0    线程安全,效率低     无参第一次扩容至10,从第二次开始按照2倍扩容
名称底层结构版本线程安全(同步)效率扩容倍数
ArrayList可变数组1.2线程不安全无参第一次扩容至10,从第二次开始按照1.5倍扩容
Vector可变数组1.0线程安全无参第一次扩容至10,从第二次开始按照2倍扩容

集合总结

最后,我把本章所有的集合整理了一下,整合了一个excel文件,需要的可以自行下载。当然,你也可以根据自己的理解整理,这里仅供参考
集合excel整理本章所有集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值