Java 集合框架

集合框架

集合:把具有相同数据类型的一组变量,汇聚成一个整体,就被称之为集合。

集合框架:为了表示和操作集合而规定的一种统一标准的体系结构。最简单的集合如数组、队列和列表等。任何集合框架一般包含:对外的接口、接口的实现和对集合运算的算法。

  • 接口:即表示集合的抽象数据类型(规范)。接口提供了让我们对集合中所表示的内容进行单独操作的方式(标准)。
  • 实现:也就是集合框架中接口的具体实现。实际上它们就是那些可复用的数据结构。
  • 算法:在一个实现了某个集合框架中的接口对象身上完成了某种有用的计算的方法,例如查找、排序等。

接口的体系结构

img

Collection接口

对单个元素进行存放的最大接口规范。针对不同的方式它有不同的实现。

List接口

是Collection接口的子接口,主要针对于线性操作来提出的规范。

特点:可重复,有序的集合

Vector实现类

线性队列式结构的一种实现,它是线程安全的,多个线程同时对集合操作时保证了安全。

特点:数组结构、查询方便(只需要下标就行)、线程安全的,插入和删除的效率低下(涉及其后元素的位移)

// 如何产生集合
    public static void a() {
        // 产生了一个空集合,集合只能存放String类型的数据
        Vector<String> vector = new Vector<>();
        // 以 vector 集合为蓝本,复制产生了一个新集合
        Vector<String> vector1 = new Vector<>(vector);
        System.out.println(vector);
        System.out.println(vector1);
        String[] array = new String[10]; // 定义了一个String数组,长度为10
        // array[1] = 9; ❌ 需要String类型,提供的是int
    }

    // 集合的常用方法
    public static void b() {
        Vector<String> vector = new Vector<>();
        // 如何向集合中存放内容
        vector.add("aa"); // 向集合的末尾添加
        vector.add("bb");
        vector.add("cc");
        vector.add("dd");
        vector.add("ee");
        vector.add("dd");
        vector.add(3, "ff"); // 插入 将元素插入到指定位置
        System.out.println(vector);
        // 如何获取集合中的内容
        String v1 = vector.get(4);
        String v2 = vector.get(2);
        System.out.println(v1);
        System.out.println(v2);
        // 如何修改集合中的内容
        vector.set(1, "gg");
        System.out.println(vector);
        // 如何删除集合中的内容
        vector.remove("dd"); // 将值为"dd"的元素删除 如果有多个"dd"只删除第一个
        vector.remove(2); // 删除位置是2的元素
        // vector.clear();  // 清空集合
        System.out.println(vector);
        // 如何获取集合的长度
        int len = vector.size();
        System.out.println("集合长度是:" + len);
        // 如何判断集合是否为空
        boolean b = vector.isEmpty();
        System.out.println(b ? "空的" : "非空的");
        // 将集合转换成数组
        Object[] array = vector.toArray();
        System.out.println(Arrays.toString(array));
        // 截取集合的部分内容 [start,end)
        List<String> subList = vector.subList(1, 3);
        System.out.println(subList);
        System.out.println(vector);
    }

    static Scanner scan = new Scanner(System.in);

    // 如何查找元素
    public static void c() {
        Vector<Integer> vector = new Vector<>();
        for (int i = 0; i < 20; i++) {
            int num = (int) (Math.random() * 30 + 1);
            vector.add(num);
        }
        System.out.println(vector);
        System.out.println("----------------------------------------");
        System.out.print("请输入一个数字:");
        int num = scan.nextInt();
        // 判断 num 在集合中是否存在
        boolean b = vector.contains(num);
        System.out.println(b ? "存在" : "不存在");
        System.out.println("----------------------------------------");
        Vector<Integer> v2 = new Vector<>();
        v2.add(13);
        v2.add(14);
        v2.add(15);
        // 判断v1集合是否是目标集合的子集
        boolean b1 = vector.containsAll(v2);
        System.out.println(b1 ? "v1是集合的子集" : "v1不是集合的子集");
        System.out.println("----------------------------------------");
        // 判断 num 在集合中第一次出现的位置,如果不存在返回-1
        int index1 = vector.indexOf(num);
        // 判断 num 在从集合指定index位置开始查找第一次出现的位置,如果不存在返回-1
        int index2 = vector.indexOf(num, 3);
        // 判断 num 在集合中最后一次出现的位置,如果不存在返回-1
        int index3 = vector.lastIndexOf(num);
        System.out.println(num + "在集合中第一次出现的位置是:" + index1);
        System.out.println(num + "在集合指定位置后第一次出现的位置是:" + index2);
        System.out.println(num + "在集合中最后一次出现的位置是:" + index3);
    }

    // 如何对集合进行排序
    public static void d() {
        Vector<Integer> vector = new Vector<>();
        for (int i = 0; i < 20; i++) {
            int num = (int) (Math.random() * 100 + 1);
            vector.add(num);
        }
        System.out.println("排序之前的集合:" + vector);
        // 对集合进行排序操作
        Collections.sort(vector);
        System.out.println("排序之后的集合:" + vector);
    }

    // 对复杂(自定义)类型的操作
    public static void e() {
        // 产生了一个集合,存放的是自定义数据类型
        Vector<Person> vector = new Vector<>();
        // 常用方法和前边使用一致,不再特别说明
        // 只关心如何查找和如何排序问题
        Person p1 = new Person(1, "周依凡", (int) (Math.random() * 60 + 15));
        Person p2 = new Person(2, "费艺飞", (int) (Math.random() * 60 + 15));
        Person p3 = new Person(3, "李涛", (int) (Math.random() * 60 + 15));
        Person p4 = new Person(4, "刘振", (int) (Math.random() * 60 + 15));
        Person p5 = new Person(5, "王石林", (int) (Math.random() * 60 + 15));
        vector.add(p1);
        vector.add(p2);
        vector.add(p3);
        vector.add(p4);
        vector.add(p5);
        // p6这个对象没有存放到集合中
        Person p6 = new Person(4, "费艺飞1", (int) (Math.random() * 60 + 15));
        boolean b1 = vector.contains(p2); // p2 在集合中
        // 判断p6对象在集合中是否存在。其实我们只关心编号为6个这个Person在集合中是否存在,也就是说我们只关心值
        boolean b2 = vector.contains(p6); // p6会和集合中的每一个元素进行比较 通过equals方法来进行
        System.out.println(b1);
        System.out.println(b2);
        System.out.println("--------------------------------------------------");
        // 如何对自定义类型的集合进行排序
        /*
            排序需要2个步骤:
            1.泛型的类必须实现Comparable接口
            2.重写compareTo方法
         */
        System.out.println(vector);
        Collections.sort(vector);
        System.out.println(vector);
    }
Stack实现类

继承于Vector类,它有一些自身特有方法。实现了一个先进后出的堆栈。提供了5个特有的方法,基本的push和pop方法,还有获取到栈顶的peek方法,还可以通过empty方法测试堆栈是否为空,search方法检测一个元素在堆栈的位置。

特点:数组结构、查询方便(只需要下标就行)、线程安全的,有自身特有方法,插入和删除的效率低下(涉及其后元素的位移)

// 1.如何产生集合对象
Stack<String> stack = new Stack<>();
// 2.集合的常用方法  这里只讨论特有方法,继承下来的方法不再重复讲解
// 等同于add(e);操作添加到集合的末尾
stack.push("aa");
stack.push("bb");
stack.push("cc");
stack.push("dd");
System.out.println(stack);
// 获取集合的元素
// 获取到集合中最后位置的元素
String v3 = stack.peek();
String v4 = stack.peek();
System.out.println(v3);
System.out.println(v4);
System.out.println(stack);
// 获取到集合中最后位置的元素 并会删除这个元素
String v1 = stack.pop();
String v2 = stack.pop();
System.out.println(v1);
System.out.println(v2);
System.out.println(stack);
// 检测堆栈是否为空
boolean b = stack.empty();
System.out.println(b);
// 检测堆栈是否存在某个元素
int index = stack.search("aa");
System.out.println("返回的位置是:" + index);
ArrayList实现类🌟🌟🌟🌟

就是传说中的动态数组,也是我们最常用的集合。它允许任何符合规则的元素插入。每一个ArrayList初始容量都是0,当第一次向集合中添加元素时,系统会自动扩充集合的长度,以后每一次添加元素时如果容量不够仍会自动扩容。和Vector类是基本一致的,除过它不是线程安全的。目前的规范标准都推荐使用ArrayList。

特点:数组结构、查询方便(只需要下标就行)、线程不安全的,插入和删除的效率低下(涉及其后元素的位移)

基本数据类型操作
public static void a() {
    // 1.如何产生对象
    // ArrayList<String> list = new ArrayList<>();
    // 一般推荐写法
    List<String> list = new ArrayList<>();
    // 2.集合的常用方法
    list.add("aa");
    list.add("bb");
    list.add("cc");
    list.add(2, "dd");
    System.out.println(list);
    String v1 = list.get(1);
    System.out.println(v1);
    list.set(2, "ee");
    System.out.println(list);
    list.remove(1); // 删除指定位置的元素
    list.remove("aa"); // 删除指定内容的元素
    System.out.println(list);
    list.clear();
    System.out.println(list);
    int len = list.size();
    System.out.println("集合的长度:" + len);
    boolean b = list.isEmpty();
    System.out.println("是否是空:" + b);
}

// 如何排序常见数据类型的集合
public static void b() {
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
        int num = (int) (Math.random() * 100 + 1);
        list.add(num);
    }
    System.out.println("排序之前的内容:");
    System.out.println(list);
    // 通过集合框架中提供的一个算法类来完成
    Collections.sort(list); // 对集合进行升序操作
    System.out.println("排序之后的内容:");
    System.out.println(list);
}

private static Scanner scan = new Scanner(System.in);

// 查找元素在集合中的位置
public static void c() {
    System.out.println("Input:");
    int num = scan.nextInt();
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 20; i++) {
        int num1 = (int) (Math.random() * 10 + 1);
        list.add(num1);
    }
    System.out.println(list);
    boolean b = list.contains(num);
    System.out.println("是否存在:" + b);
    int index1 = list.indexOf(num); // 找出第一次出现的位置 不存在返回-1
    int index2 = list.lastIndexOf(num); // 找出最后一次出现的位置 不存在返回-1
    System.out.println(index1);
    System.out.println(index2);
}
复杂数据类型操作
// ArrayList对复杂类型的操作
public class DemoD {
    // 基本的创建对象,CRUD(增删改查)的方法
    public static void a() {
        // 产生了一个集合,这个集合只能存放Person类型的数据
        List<Person> list = new ArrayList<>();
        // 产生了四个对象
        Person p1 = new Person(1, "张三", '男', 23);
        Person p2 = new Person(2, "李四", '女', 21);
        Person p3 = new Person(3, "王武", '男', 28);
        Person p4 = new Person(4, "马六", '男', 25);
        // 将这四个对象存放到集合中
        list.add(p1);
        list.add(p2);
        list.add(1, p3);
        list.add(p4);
        System.out.println(list);
        // 获取到指定位置的元素
        Person p5 = list.get(3);
        System.out.println(p5);
        // 修改指定位置的元素
        Person p6 = new Person(5, "大白", '男', 19);
        list.set(1, p6);
        System.out.println(list);
        // 删除元素
        list.remove(1);
        list.remove(p1);
        System.out.println(list);
        // 清空
        list.clear();
        // 获取长度
        int len = list.size();
        System.out.println(len);
    }


    // 讲解了复杂(自定义)数据类型的排序问题
    /*
        1.泛型类必须实现Comparable接口
        2.泛型类重写compareTo方法,自定义规则
        3.调用Collections.sort(list);来进行排序
     */
    public static void b() {
        List<Person> list = new ArrayList<>();
        Person p1 = new Person(1, "张三", '男', 23);
        Person p2 = new Person(2, "李四", '女', 21);
        Person p3 = new Person(3, "王武", '男', 28);
        Person p4 = new Person(4, "马六", '男', 25);
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        list.add(p2);
        System.out.println("排序之前的集合:");
        for (int i = 0; i < list.size(); i++) {
            Person p = list.get(i);
            System.out.println(p);
        }
        // 如何对集合排序 要求泛型必须实现一个接口Comparable
        Collections.sort(list);
        System.out.println("排序之后的集合:");
        for (int i = 0; i < list.size(); i++) {
            Person p = list.get(i);
            System.out.println(p);
        }
    }

    /*
        讲解了复杂数据类型的查找问题
        1.重写equals方法 自定义规则
        2.调用contains或者indexOf方法
     */
    public static void c() {
        List<Person> list = new ArrayList();
        Person p1 = new Person(1, "张三", '男', 26);
        Person p2 = new Person(2, "李四", '女', 22);
        Person p3 = new Person(3, "王武", '男', 21);
        Person p4 = new Person(4, "马六", '男', 27);
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        int len = list.size();
        System.out.println("集合长度是:" + len);
        boolean b1 = list.contains(p1);
        System.out.println(b1 ? "存在" : "不存在");
        int index1 = list.indexOf(p1);
        System.out.println("位置是:" + index1);
        System.out.println("----------------------------------------------");
        // 只关心对象的值在集合中的元素是否有重复
        // 产生了一个新对象
        Person p5 = new Person(3, "王武", '男', 21);
        System.out.println("p3和p5的内存地址是否相等?" + (p3 == p5));
        System.out.println("p3和p5的equals方法返回结果是否相等?" + p3.equals(p5));
        boolean b2 = list.contains(p5);
        System.out.println(b2 ? "存在" : "不存在");
        int index2 = list.indexOf(p5);
        System.out.println("位置是:" + index2);
        System.out.println("----------------------------------------------");
        Person p6 = p3;
        System.out.println("p3和p6是否相等?" + (p3 == p6));
        boolean b3 = list.contains(p6);
        System.out.println(b3 ? "存在" : "不存在");
        int index3 = list.indexOf(p6);
        System.out.println("位置是:" + index3);
    }
    public static void main(String[] args) {
        c();
    }

}
LinkedList实现类

是List接口的一种实现,它是一种双向链表结构,在执行查询时效率比较低下,但是插入和删除效率比较高。

/*
    1.如何产生集合对象
    2.集合的常用方法
    3.如何查找和排序
    4.其他的注意事项
 */
public class DemoB {

    public static void a() {
        // 产生LinkedList集合对象
        LinkedList<String> list = new LinkedList<>();
        // 常用方法
        list.add("aa");
        list.add("bb");
        list.add(1, "cc");
        // 特有方法
        list.addFirst("dd"); // 添加到第一个位置
        list.addLast("ee"); // 就是list.add("ee");
        System.out.println(list);
        String v1 = list.get(1);
        // 特有方法
        String v2 = list.getFirst();
        String v3 = list.getLast();
        System.out.println("获取指定位置元素:" + v1);
        System.out.println("获取第一个元素:" + v2);
        System.out.println("获取最后一个元素:" + v3);
        list.set(2, "ff");
        System.out.println(list);
        list.remove(1);
        list.remove("ff");
        // 特有方法
        list.removeFirst();
        list.removeLast();
        System.out.println(list);
        int len = list.size();
        System.out.println("长度是:" + len);
        list.clear();
        boolean b = list.isEmpty();
        System.out.println(b ? "空的" : "非空的");
    }

    private static Scanner scan = new Scanner(System.in);

    // 基本类型的排序和查找
    public static void b() {
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < 10; i++) {
            int num = (int) (Math.random() * 100 + 1);
            list.add(num);
        }
        System.out.println(list);
        Collections.sort(list); // List中的四个实现类它们的排序是一样的
        System.out.println(list);
        // List中的四个实现类它们的查找也是一样的
        System.out.println("请输入:");
        int num = scan.nextInt();
        boolean b = list.contains(num);
        int index1 = list.indexOf(num);
        int index2 = list.lastIndexOf(num);
        System.out.println("是否存在?" + b);
        System.out.println("第一次出现的位置:" + index1);
        System.out.println("最后一次出现的位置:" + index2);
    }

    // 自定义类型的排序和查找
    public static void c() {
        LinkedList<Person> list = new LinkedList<>();
        Person p1 = new Person(1, "张三", '男', 21);
        Person p2 = new Person(2, "李四", '女', 27);
        Person p3 = new Person(3, "王武", '男', 23);
        Person p4 = new Person(4, "马六", '男', 25);
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        // 排序之前:
        for (Person p : list) {
            System.out.println(p);
        }
        System.out.println("------------------------------------------------");
        Collections.sort(list); // 同ArrayList的写法
        // 排序之后:
        for (Person p : list) {
            System.out.println(p);
        }
        // 查找 和ArrayList写法完全一致
        System.out.println("------------------------------------------------");
        Person p5 = new Person(3, "王五", '男', 26);
        boolean b = list.contains(p5);
        int index = list.indexOf(p5);
        System.out.println("是否存在?" + b);
        System.out.println("第一次出现的位置:" + index);
    }

    public static void main(String[] args) {
        c();
    }
}
List集合实现类的分析
  • ArrayList、Vector和Stack都是动态数组,它们查询速度很快,但是插入删除速度慢。
  • LinkedList是双向链表结构,插入删除块,查询速度慢,
  • Vector是线程安全的集合,Stack是Vector的子类,它是一个先进后出的结构。
  • 一般情况下,我们推荐使用ArrayList。

Set接口

是Collection接口的子接口,它主要针对于散列式接口来提出的规范。

特点:不可重复(不允许存放重复的元素),无序(没有索引下标)。

HashSet实现类🌟🌟🌟

HashSet是Set集合最常用的实现类,经典表现。是按照Hash算法来存储元素的,因此具有很好的存放功能。

特点

  1. 不保证元素的顺序
  2. HashSet不是线程安全的
  3. 可以存放null值
  4. 值的内容不允许重复
产生HashSet集合
Set<Integer> set = new HashSet<>();
常见的方法
//添加元素
set.add(99);
set.add(23);
set.add(56);
set.add(78);
/*
	// 不能存放重复内容,存放时要判断元素在集合中是否存在
	首先通过循环来和集合中的每一个元素进行比较
      1.获取到当前元素的hash值(通过调用hashCode()来获取) 和集合中元素的hash值比较相等时
      2.当前元素和集合中元素的equals()进行比较
      3.如果都相等 则代表这个元素在集合中存在,否则 不存在
*/
set.add(56); 
set.add(null);
System.out.println(set);
// 删除元素
set.remove(23); // 只能删除指定元素  不能删除索引
System.out.println(set);
// 获取元素 没有 无法获取
// 只能通过迭代器来遍历
for (Integer i : set) {
    System.out.print(i + "\t");
}
System.out.println();
// 修改元素 无法修改

int len = set.size();
System.out.println(len);
查找集合中是否存在内容
public static void c() {
    // 产生了一个集合
    HashSet<School> set = new HashSet<>();
    // 产生了四个对象
    School s1 = new School(1, "清华大学");
    School s2 = new School(2, "北京大学");
    School s3 = new School(3, "西安交通大学");
    School s4 = new School(4, "长安大学");
    // 存放到了集合中
    set.add(s1);
    set.add(s4);
    set.add(s3);
    set.add(s2);
    // 通过迭代器遍历集合
    for (School s : set) {
        System.out.println(s);
    }
    School s5 = new School(3, "西安交通大学");
    /*
        首先通过循环来和集合中的每一个元素进行比较
        1.获取到当前元素的hash值(通过调用hashCode()来获取) 和集合中元素的hash值比较相等时
        2.当前元素和集合中元素的equals()进行比较
        3.如果都相等 则代表这个元素在集合中存在,否则 不存在
     */
    boolean b = set.contains(s5);
    System.out.println(b ? "存在" : "不存在");
    set.add(s5); // HashSet集合在存放内容时 会判断这个内容是否在集合中存在 存放不进去
    System.out.println(set.size());
}
// 学校类
public class School {
    private Integer id;
    private String name;
    /*
        还需要重写hashCode方法
     */
    public int hashCode(){
        return id; // 返回的hash值设置为id
    }
    /*
        重写equals方法 设置自己的规则
        自定义规则为:只要id一致就行
     */
    public boolean equals(Object o) {
        int myId = this.getId();
        School s = (School) o;
        int itId = s.getId();
        return myId == itId;
    }
}
TreeSet实现类

TreeSet是一个红黑树的结构,录入数据后能够进行排序,如果是自定义数据类型必须实现Comparable接口。

  • 无序:它不是一个线性结构,不知道在队列中的位置
  • 有序:在存放时会比较大的在右子节点,小的在左子节点

⚠️ 注意

  1. TreeSet不能存放null值。
  2. TreeSet强制排序,泛型类必须实现Comparable接口。
产生对象和常见方法
TreeSet<Integer> set = new TreeSet<>();
set.add(28);
set.add(99);
set.add(19);
set.add(33);
set.add(61);
set.add(33); // Set集合中不能存放重复数据
// set.add(null); ❌ TreeSet集合不能存放null
System.out.println(set);
set.remove(19);
System.out.println(set);
int len = set.size();
System.out.println(len);
boolean b = set.contains(19);
System.out.println(b);
int first = set.first(); // 获取到根结点
System.out.println(first);
// 通过迭代器来进行遍历
for (Integer i : set) {
    System.out.print(i + "\t");
}
复杂类型在TreeSet的使用
TreeSet<Lover> set = new TreeSet<>();
Lover l1 = new Lover(1, "杨超越", "💃");
Lover l2 = new Lover(2, "羽生结弦", "⛸️");
Lover l3 = new Lover(3, "谷爱凌", "🎿");
// 也需要判断元素在集合中是否存在
set.add(l1);
set.add(l2);
set.add(l3);
System.out.println(set);
// 产生了一个新对象
Lover l4 = new Lover(3, "谷爱凌", "🎿");
// TreeSet在判断是否存在时 通过compareTo方法来进行 如果返回的是0 则认为是一个对象
boolean b = set.contains(l4);
System.out.println(b ? "存在" : "不存在");
LinkedHashSet实现类

LinkedHashSet是HashSet的子类,具有HashSet的特性,也是根据元素的HashCode值来判断元素。但它使用链表维护元素的次序,元素的顺序与添加顺序一致。由于LinkedHashSet需要维护元素的插入顺序,因此性能上要低于HashSet。

Set集合实现类的分析
  • HashSet的性能是最好的,因为TreeSet要排序,LinkedHashSet需要维护次序。大部分情况下我们都应使用HashSet。
  • LinkedHashSet是HashSet的子类,具有HashSet的特性,又维护了插入顺序。
  • 如果我们需要对Set集合进行排序,那么推荐使用TreeSet。
  • HashSet和LinkedHashSet都是Hash结构的,而TreeSet是红黑树结构的。

Queue接口

是Collection接口的子接口,先进先出的一种规范体现。在实际应用中使用较少。就是队列结构,它只允许在队列的前端进行删除操作,而在队列的后端进行插入操作。

// LinkedList也实现了队列接口
Queue<String> queue = new LinkedList<>();
queue.offer("aa"); // 同add(e);
queue.offer("bb");
queue.offer("cc");
System.out.println(queue);
String v1 = queue.poll(); // 获取到队首的内容 取出来
System.out.println(v1);
System.out.println(queue);
String v2 = queue.element(); // 获取到队首的内容
System.out.println(v2);
System.out.println(queue);

Map接口

Map接口采用键值对的方式来存储数据,将一个值(Value)存放到集合中,给它又起了一个别名(Key),保存具有映射关系的数据,因此,Map集合中存放两组数据,一组用于存放值,另一组用于存放键,其中值允许重复,键不允许重复。

HashMap实现类🌟🌟🌟

HashMap是基于Hash算法实现的一个集合,是map中最常用的一个实现类。值可以重复,健不能重复,如果重复会覆盖掉原有内容。HashMap的键和值都允许存放null。键是Hash结构的。

产生HashMap集合
// 产生HashMap对象 存放的内容只能是int类型,起的名字(Key)是String类型
Map<String, Integer> map = new HashMap<>();
HashMap的常用方法
// 常用方法
// 添加和修改
map.put("a", 87); // 将87存放到map集合中起了一个名字a
map.put("b", 97);
map.put("c", 97);
map.put("d", 91);
map.put("d", 33); // 修改 Key重复会覆盖原有内容
map.put("e", null);
map.put(null, 87);
System.out.println(map);
// 获取
int v1 = map.get("a"); // 通过键获取到值
//int v2 = map.get("m"); // 不存在报错
System.out.println(v1);
//System.out.println(v2);
// 删除
map.remove("d"); // 根据Key删除指定元素
System.out.println(map);
// 获取长度
int len = map.size();
System.out.println("长度:" + len);
排序和查找
// HashMap集合和HashSet集合一致都不能排序
// HashMap集合和HashSet集合查找方式一致
public static void b(){
    Map<String,Integer> map = new HashMap<>();
    map.put("a",33);
    map.put("b",46);
    boolean b1 = map.containsValue(46); // 判断46是否在值集合中
    boolean b2 = map.containsKey("a");// 判断a是否在键集合中
    System.out.println(b1);
    System.out.println(b2);
}
特有的几个方法
Map<String, Integer> map = new HashMap<>();
map.put("a", 87); // 将87存放到map集合中起了一个名字a
map.put("b", 97);
map.put("c", 97);
map.put("d", 91);
// 获取到键集合
Set<String> keys = map.keySet(); // 获取到所有的键
// 获取到值集合
Collection<Integer> values = map.values(); // 获取到所有的值
System.out.println(keys);
System.out.println(values);

TreeMap实现类

TreeMap也是一个红黑树结构,它的Key集是红黑树结构。也就是说在存放数据时会按照Key进行排序。

Hashtable实现类

Hashtable是基于Hash算法实现的一个集合,值可以重复,健不能重复,如果重复会覆盖掉原有内容。Key集是Hash结构的。它是一个线程安全的集合。方法和HashMap一致。

ConcurrentHashMap实现类

ConcurrentHashMap是基于Hash算法实现的一个集合,值可以重复,健不能重复,如果重复会覆盖掉原有内容。Key集是Hash结构的。它是一个分段锁的操作,把集合中的数据分别上锁,影响的面就比较小一些。

LinkedHashMap实现类

LinkedHashMap使用双向链表来维护键值对,维护了插入的顺序,保证了迭代顺序。仍然是以Key集来维护的。

Map实现类对于null的操作

// key和value都能存放null
HashMap<String, String> map1 = new HashMap<>();
map1.put(null, null);
System.out.println(map1);
// key不能为null,value可以是null
TreeMap<String, String> map2 = new TreeMap<>();
//map2.put(null,"a");
System.out.println(map2);
// key和value都不允许为null
Hashtable<String, String> map3 = new Hashtable<>();
//map3.put(null, "a");
System.out.println(map3);
// key和value都能存放null
LinkedHashMap<String, String> map4 = new LinkedHashMap<>();
map4.put(null, null);
System.out.println(map4);
// key和value都不允许为null
ConcurrentHashMap<String, String> map5 = new ConcurrentHashMap<>();
map5.put(null, "a");
System.out.println(map5);

迭代器

迭代器(iterator)有时又称光标(cursor)是程序设计的软件设计模式,可在容器对象(container,例如链表或数组)上遍访的接口,设计人员无需关心容器对象的内存分配的实现细节。

    // 通过游标模式迭代集合
    public static void a() {
        System.out.println(set);
        // 将set集合转换成游标
        Iterator<Integer> it = set.iterator();
        /*int first = it.next();
        System.out.println(first);
        int b = it.next();
        System.out.println(b);*/
        while (it.hasNext()) { // 判断是否有下一个
            int next = it.next(); // 获取到下一个
            System.out.println(next);
        }
    }

    // 游标模式的缩写形式foreach写法 增强for
    public static void b() {
        System.out.println(set);
        for (Integer next : set) {
            System.out.println(next);
        }
    }

泛型

泛泛的类型,在定义时并不清楚变量的具体数据类型,只有在使用时才确定。

public class DemoB<E,T> {
    // 定义了一个变量a 数据类型是int
    int a;
    // 定义了一个变量b 数据类型未知,产生对象时确定
    E b;
    T t;
    public static void main(String[] args) {
        DemoB<Integer,String> b = new DemoB<>();
    }
}

泛型的注意:

  1. 产生对象时,未指定泛型类型,那么泛型类型就是Object。
  2. 泛型不能是原始数据类型 可以使用对应的包装类。
  3. 泛型可以书写多个,直接使用,隔开就行。
  4. 泛型按照定义次序依次设置类型,不能少设或者多设。

值传递和引用传递问题

public class DemoC {

    // 原始类型 存放的是值
    public static void a() {
        int a = 1;
        List<Integer> list = new ArrayList<>();
        list.add(a); // 理解成集合中存放的是1 相当于 list.add(1);
        System.out.println(list);
        a = 4; // 重新创建了一个变量 也起了一个名字叫a
        System.out.println(list);
    }

    // 集合中存放的是对象的内存地址
    public static void b() {
        Person p = new Person(1, "张三", '男', 23);
        List<Person> list = new ArrayList<>();
        list.add(p); // 存放的是内存地址(引用)
        System.out.println(list);
        p.setName("李四"); // 修改了p 集合也会发生改变
        System.out.println(list);
    }

    // 集合中存放常量问题(String问题)
    public static void c() {
        String s = "aaa"; // 常量字符串 值不能发生改变的
        List<String> list = new ArrayList<>();
        list.add(s);
        System.out.println(list);
        s = "abc"; // 重新创建一个变量(对象)
        System.out.println(list);
    }

    // 重新创建对象问题
    public static void d() {
        Person p = new Person(1, "张三", '男', 24);
        List<Person> list = new ArrayList<>();
        list.add(p);
        System.out.println(list);
        // 新创建一个对象 还起了一个名字 另一内存地址
        p = new Person(2, "王五", '女', 22);
        System.out.println(list);
    }

    public static void main(String[] args) {
        d();
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值