java 集合详解

1.java里,集合包含Collection(单列集合)和Map(双列集合),两者均为根接口,其下还有多个实现类。关系图
1)Collection关系图
在这里插入图片描述

2)Map关系图
在这里插入图片描述
2.集合概述

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

/**
 * @Author wfj
 * @Date 2021/6/11
 * @Description 集合
 * @Version 1.0
 */

public class CollectionTest {
    /**
     * 集合框架的概述
     * 1.集合,数组都是对多个数据进行存储操作的结构,简称java容器
     *  说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,jpg..)
     *
     *一、数组
     * 2.1 数组特点
     *      一旦初始化以后,其长度就确定了
     *      数组一旦定义好,其元素的的类型也确定了,我们也就只能操作指定类型的数据了
     *      比如int[] arr,String[] arrs
     * 2.2 数组缺点
     *      1)一旦初始化后,其长度不可修改
     *      2)数组中提供的方法非常有限,对于增,删,改,查,非常不便,同时效率不高
     *      3)获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
     *      4)数组存储数据的特点:有序,可重复,对于无序,不可重复的需求,不能满足
     *
     * 二、集合框架
     *      Collection接口:单列集合,用来存储一个一个的对象
     *          --List接口:存储有序的,可重复的数据
     *              --ArrayList,LinkedList,Vector
     *
     *          --Set接口:存储无序的,不可重复的数据
     *              --HashSet,LinkedHashSet,TreeSet
     *      Map接口:双列集合,用来存储一对一(key-value)一对的数据
     *          --HashMap,LinkedHashMap,TreeMap,HashTable,Properties
     */
    @Test
    public void test1() {
        Collection collection = new ArrayList();
        //添加元素
        collection.add("a");
        collection.add("b");
        collection.add(123);
        collection.add(new Date());
        System.out.println(collection.size());//4

        Collection collection2 = new ArrayList();
        collection2.add("q");
        collection2.add(99);
        //将一个集合的所有元素添加到新集合里
        collection.addAll(collection2);
        System.out.println(collection.size());//6

        //清空元素
        collection.clear();

        //判断当前集合是否为空
        System.out.println(collection.isEmpty());//true

    }
}

3.Collection一些常用方法

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * @Author wfj
 * @Date 2021/6/15
 * @Description 集合常用方法
 * @Version 1.0
 */

public class CollectionTest1 {

    @Test
    public void test1() {
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add("abc");
        coll1.add(false);
        coll1.add(new String("hello"));
        Dog dog = new Dog("小白",3);
        coll1.add(dog);
        //contains方法,判断集合里是否包含某一个元素
        //注意,如果元素为某一个对象时,对象对应的javabean最好重写equals方法
        System.out.println(coll1.contains(new String("hello")));//true
        System.out.println(coll1.contains(new Dog("小白",3)));//true
        Collection coll2 = Arrays.asList(123, "abc");
        //containsAll,判断某个集合是否包含另外一个集合的所有元素
        System.out.println(coll1.containsAll(coll2));//true
    }

    @Test
    public void test2() {
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add("a");
        coll1.add(true);
        coll1.add(new Dog("小黑",5));
        boolean isRemove = coll1.remove(123);
        System.out.println(isRemove);//true
        //Dog要重写equals方法
        boolean isRemove2 = coll1.remove(new Dog("小黑", 5));
        System.out.println(isRemove2);//true
        System.out.println(coll1.toString());//[a, true]

        //removeAll()从当前集合中移除另外一个集合中的所有元素
        Collection coll2 = new ArrayList();
        coll2.add(1);
        coll2.add(2);
        coll2.add("a");
        coll2.add("b");
        Collection coll3 = new ArrayList();
        coll3.add(1);
        coll3.add("b");
        boolean isRemoveAll = coll2.removeAll(coll3);
        System.out.println(isRemoveAll);//true
        System.out.println(coll2.toString());//[2, a]
    }

    @Test
    public void test3() {
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add("a");
        coll1.add(true);
        coll1.add(new Dog("小黑",5));
        Collection coll2 = Arrays.asList(123, "a");
        //retainAll,求两个集合的交集,并且返回coll1
        coll1.retainAll(coll2);
        System.out.println(coll1.toString());//[123, a]
    }

    @Test
    public void test4() {
        //equals() 判断两个集合的元素是否全都相同
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add("a");
        coll1.add(true);
        coll1.add(new Dog("小黑",5));
        Collection coll2 = new ArrayList();
        coll1.add(123);
        coll1.add("a");
        coll1.add(true);
        coll1.add(new Dog("小黑",5));
        System.out.println(coll1.equals(coll2));//true

        //获取哈希值
        System.out.println(coll1.hashCode());//-851290633

        //集合转数组
        Object[] objects = coll1.toArray();
        for (int i = 0; i <objects.length; i++) {
            System.out.println(objects[i]);
        }

        //数组转集合
        List<String> list = Arrays.asList(new String[]{"AA", "bb", "cc"});
        System.out.println(list.toString());//[AA, bb, cc]

        //注意:如果是基本数据类型的数组,其会把这个数组对象当作一个元素
        List arr1 = Arrays.asList(new int[]{11,22});
        System.out.println(arr1.size());//1

        List arr2 = Arrays.asList(new Integer[]{11,22,33});
        System.out.println(arr2.size());//3
    }
}

4.List接口详解

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;
import org.omg.PortableServer.LIFESPAN_POLICY_ID;

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

/**
 * @Author wfj
 * @Date 2021/6/15
 * @Description List接口
 * @Version 1.0
 */

public class ListTest {
    /**
     *  1.List接口:存储有序的,可重复的数据
     *          --ArrayList 最常用的一个实现类,线程不安全的,效率高,底层使用数组
     *          --LinkedList 对于频繁地使用插入,删除这些操作,使用LinkedList效率比较高(数组增加,删除元素,其他元素的位置也要变更,
     *          但是如果是链表的话,直接修改几个元素的指针地址就行了),其底层使用双向链表存储
     *          --Vector jdk1.0发布的,线程安全的,效率低底层使用数组
     *
     *   ArrayList,LinkedList,Vector的异同?
     *   相同点:三个类都是实现了List接口,存储数据的特点相同,存储有序的,可重复的数据
     *   不同点:见上
     *
     *  2.ArrayList的源码分析:
     *      2.1 jdk7(创建ArrayList对象的方式类似于饿汉模式)
     *          ArrayList list = new ArrayList() //底层创建了长度是10的Object[]数组elementDate
     *          list.add(1);//elementData[0] = new Integer(1)
     *          ...
     *          list.add(11)//如果此次的添加导致底层elementData数组容量不够,则扩容
     *          默认情况下,扩容为原来的1.5倍,同时需要将旧数组的元素赋值到新数组,所以开发中,如果
     *          确定了元素的个数,建议使用带参的构造器
     *
     *      2.2 jdk8 (创建ArrayList对象的方式类似于懒汉模式,节省内存)
     *          ArrayList list = new ArrayList();//底层Object[] elementDate初始化为{},并没有创建长度为10的数组
     *          list.add(1); //第一个调用list时,底层才创建了长度为10的数组,并将元素添加到数组中
     *          其他无异
     *
     *  3.LinkedList的源码分析:
     *      LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,属性值为null
     *      list.add(1); //将1封装到Node中,创建了Node对象
     *
     *      Node的定义,体现了LinkedList双向链表的说话
     *       private static class Node<E> {
     *         E item;
     *         Node<E> next;
     *         Node<E> prev;
     *
     *         Node(Node<E> prev, E element, Node<E> next) {
     *             this.item = element;
     *             this.next = next;
     *             this.prev = prev;
     *         }
     *     }
     *
     *  4.Vector的源码分析:
     *      jdk7和jdk8中通过Vector()构造器创建对象时,底层创建了长度为10的数组
     *      在扩容方面,默认扩容长度为原来的2倍
     *
     *
     */

    //List接口中常用方法
    @Test
    public void tes1() {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list);//[1, 2, 3]

        //add()往指定索引位置插入元素
        list.add(1,"a");
        System.out.println(list);//[1, a, 2, 3]

        //addAll()从指定索引位置开始将另外一个集合中所有的元素添加进来
        List list1 = Arrays.asList(4,5,6);
        list.addAll(1,list1);
        System.out.println(list);//[1, 4, 5, 6, a, 2, 3]

        //get()获取第一个元素
        System.out.println(list.get(0));//1

        //indexOf() 返回该元素在集合中出现的首次位置索引,如果元素不存在,则返回-1
        System.out.println(list.indexOf("a"));//4

        //lastIndexOf() 返回该元素在集合中出现的末尾位置索引,如果元素不存在,返回-1
        System.out.println(list.lastIndexOf(2));//5

        //remove() 移除指定索引位置的元素,并且返回该元素
        Object obj = list.remove(2);
        System.out.println(obj);//5

        //set() 修改指定索引位置的元素
        list.set(0,"timi");
        System.out.println(list);//[timi, 4, 6, a, 2, 3]

        //subList(int fromIndex,int toIndex)截取集合,返回从fromIndex开始,toIndex结束,左闭右开的子集合
        //比如截取最后两个元素
        List list2 = list.subList(list.size() - 2, list.size());
        System.out.println(list2);//[2, 3]
    }

    @Test
    public void test2() {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list);
        changeList(list);
        System.out.println(list);
    }

    private void changeList(ArrayList list) {
        //默认会删除索引位置为3的元素
        list.remove(3);
        //如果要删除3这个元素,那么就得构造对象
        //list.remove(new Integer(3));
    }

}

5.Set接口详解
1)测试用到的javabean

package com.yl.pdfdemo.day08.p2;

import java.util.Objects;

/**
 * @Author wfj
 * @Date 2021/6/15
 * @Description
 * @Version 1.0
 */

public class Dog implements Comparable{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Dog() {
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dog dog = (Dog) o;
        return age == dog.age &&
                Objects.equals(name, dog.name);
    }

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

    //按照姓名从大到小排序,再按照年龄从大到小排序
    @Override
    public int compareTo(Object o) {
        if (o instanceof Dog) {
            Dog dog = (Dog)o;
            int i = -this.name.compareTo(dog.name);
            if (i != 0) {
                return i;
            } else {
                return -Integer.compare(this.age,dog.age);
            }
        }
        return 0;
    }
}

package com.yl.pdfdemo.day08.p2;

import java.util.Objects;

/**
 * @Author wfj
 * @Date 2021/6/16
 * @Description
 * @Version 1.0
 */

public class Employee implements Comparable {
    private int age;
    private String name;
    private MyDate birthDay;

    public Employee() {
    }

    public Employee(int age, String name, MyDate birthDay) {
        this.age = age;
        this.name = name;
        this.birthDay = birthDay;
    }

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    public MyDate getBirthDay() {
        return birthDay;
    }

    public void setBirthDay(MyDate birthDay) {
        this.birthDay = birthDay;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Objects.equals(name, employee.name) &&
                Objects.equals(birthDay, employee.birthDay);
    }

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

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

    //按照名字从大到小排序
    @Override
    public int compareTo(Object o) {
        if (o instanceof Employee) {
            Employee employee = (Employee)o;
            return -this.name.compareTo(employee.name);
        }
        return -1;
    }
}

package com.yl.pdfdemo.day08.p2;

/**
 * @Author wfj
 * @Date 2021/6/16
 * @Description
 * @Version 1.0
 */

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

    public MyDate() {
    }

    public MyDate(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 "MyDate{" +
                "year='" + year + '\'' +
                ", month='" + month + '\'' +
                ", day='" + day + '\'' +
                '}';
    }
}

  1. Set接口概述
package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

import java.util.*;

/**
 * @Author wfj
 * @Date 2021/6/15
 * @Description Set接口
 * @Version 1.0
 */

public class SetTest {
    /**
     *  一、Set接口:存储无序的,不可重复的数据(它本身没有定义额外的方法,我们直接使用Collection接口的方法就行)
     *      --HashSet: 作为Set接口的主要实现类,线程不安全的,可以存储null值,底层使用数组+链表
     *          --LinkedHashSet: 作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序来遍历,
     *                          在往LinkedHashSet添加数据的同时,每个数据还维护了两个引用,一个指向上前一个数据,一个指向后一个数据
     *                          所以,对于频繁的遍历操作,LinkedHashSet的效率是比HashSet要高的,其底层使用数组+链表
     *
     *      --TreeSet: 可以按照添加对象的指定属性,进行排序,底层使用二叉树
     *
     *
     *      注意:
     *      1.无序性:不等于随机性,存储的数据在底层数组中,并非按照数组索引来的顺序添加,而是根据数据的哈希值决定的
     *
     *      2.不可重复性:保证添加元素按照equals()判断时,不能返回true,即相同的元素只能添加一个
     *
     *  二·、添加元素的过程,以HashSet为例
     *      我们向HashSet中添加元素a,首先调用元素a所在的hashCode()方法,计算元素a的哈希值
     *      此哈希值接着通过某种算法计算出在HashSet底层数组中存在的位置,即索引位置,判断此位置上是否有元素
     *          如果此位置上没有元素,则元素a添加成功 ==》情况一
     *          如果此位置上有其他元素b(或者以链表的形式存在多个元素),则比较元素a与元素b的哈希值
     *              如果哈希值不相同,则元素a添加成功 ==》 情况二
     *              如果哈希值相同,进而需要调用元素a所在类的equals()方法
     *                  equals()方法返回true,元素a添加失败
     *                  equals()方法返回false,元素a添加成功 ==》情况三
     *
     *        对于情况二和情况三而言,元素a与已经存在指定索引位置上的数据以链表的方式存储
     *        jdk7:元素a放到数组中,指向原来的元素
     *        jdk8:原来的元素还是在数组中,指向元素a
     *        总结:七上八下
     *
     *        要求:如果往Set中,添加数据,其所在的类必须要从重写hashCode()方法和equals()方法,
     *        重写的hashCode()方法和equals()方法尽可能保持一致,相等的对象必须具有相等的散列码
     */

    @Test
    public void test1() {
        Set set = new HashSet();
        set.add(1);
        set.add("a");
        set.add(100);
        set.add(66);
        set.add(1);//添加了重复元素,其不会添加到集合里
        set.add("b");
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next());//1 a 66 b 100
        }
        System.out.println();
        Set set1 = new LinkedHashSet();
        set1.add(1);
        set1.add("a");
        set1.add(100);
        set1.add(66);
        set1.add("b");
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()) {
            //会按照添加的顺序来遍历,但是实际上并不是有序的。。。
            System.out.print(iterator1.next());//1 a 100 66 b
        }

    }

    //TreeSet
    @Test
    public void test2() {
        /**
         *  向TreeSet中添加数据,要求是相同类的对象
         *  两种排序方式:自然排序(实现Comparable接口重写compareTo()方法) 定制排序(Comparator)
         *  自然排序中,比较两个对象是否相等的标准为:compareTo()返回0,不再是equals()
         *  定制排序中,比较两个对象是否相等的标准为:compareTo()返回0,不再是equals()
         *
         *
         */
        TreeSet set = new TreeSet();
        set.add(1);
        set.add(-1);
        set.add(11);
        set.add(1111);
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("==========================");

        //自然排序
        TreeSet set1 = new TreeSet();
        set1.add(new Dog("xi",13));
        set1.add(new Dog("xing",13));
        set1.add(new Dog("x",13));
        set1.add(new Dog("xibao",13));
        set1.add(new Dog("xibao",19));
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
        System.out.println("==========================");
        //定制排序
        TreeSet set2 = new TreeSet(new Comparator() {
            //按照年龄从大到小排序,姓名从小到大排序
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Dog && o2 instanceof Dog) {
                    Dog d1 = (Dog)o1;
                    Dog d2 = (Dog)o2;
                    int i = -Integer.compare(d1.getAge(), d2.getAge());
                    if (i != 0) {
                        return i;
                    } else {
                        return d1.getName().compareTo(d2.getName());
                    }
                }
                return -1;
            }
        });
        set2.add(new Dog("xi",13));
        set2.add(new Dog("xing",13));
        set2.add(new Dog("x",13));
        set2.add(new Dog("xibao",13));
        set2.add(new Dog("xibao",19));
        Iterator iterator2 = set2.iterator();
        while (iterator2.hasNext()) {
            System.out.println(iterator2.next());
        }
    }

    //面试题
    @Test
    public void test3() {
        HashSet set = new HashSet();
        Dog dog1 = new Dog("小白",13);
        Dog dog2 = new Dog("小兰",15);
        set.add(dog1);
        set.add(dog2);
        System.out.println(set);//[Dog{name='小白', age=13}, Dog{name='小兰', age=15}]
        dog1.setName("小黑");
        set.remove(dog1);//注意,这里删除的索引位置来源(name为小黑,age为13的哈希值,数组中没有这个索引位置,所以什么都没删除到)
        System.out.println(set);//[Dog{name='小黑', age=13}, Dog{name='小兰', age=15}]
        set.add(new Dog("小黑",13));//[Dog{name='小黑', age=13}, Dog{name='小黑', age=13}, Dog{name='小兰', age=15}]
        System.out.println(set);
        set.add(new Dog("小白",13));//[Dog{name='小黑', age=13}, Dog{name='小黑', age=13}, Dog{name='小白', age=13}, Dog{name='小兰', age=15}]
        System.out.println(set);
    }
}

3)练习

package com.yl.pdfdemo.day08.p2;

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

/**
 * @Author wfj
 * @Date 2021/6/16
 * @Description TreeSet练习
 * @Version 1.0
 */

public class ExceTest {
    public static void main(String[] args) {
        Employee employee = new Employee(17,"bin",new MyDate("2020","10","11"));
        Employee employee1 = new Employee(11,"ain",new MyDate("2020","10","11"));
        Employee employee2 = new Employee(19,"lin",new MyDate("2020","10","11"));
        Employee employee3 = new Employee(7,"cin",new MyDate("2020","10","11"));
        TreeSet set = new TreeSet();
        set.add(employee);
        set.add(employee1);
        set.add(employee2);
        set.add(employee3);
        Iterator iterator = set.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        System.out.println("=============");
        //定制排序
        TreeSet set1 = new TreeSet(new Comparator() {
            //按照年龄从大到小排序
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Employee && o2 instanceof Employee) {
                    Employee e1 = (Employee)o1;
                    Employee e2 = (Employee)o2;
                    return -Integer.compare(e1.getAge(),e2.getAge());
                }
                return -1;
            }
        });
        set1.add(employee);
        set1.add(employee1);
        set1.add(employee2);
        set1.add(employee3);
        Iterator iterator1 = set1.iterator();
        while(iterator1.hasNext()) {
            System.out.println(iterator1.next());
        }
    }
}

6.集合的遍历,使用迭代器

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/**
 * @Author wfj
 * @Date 2021/6/15
 * @Description 集合元素的遍历操作,使用迭代器接口
 * @Version 1.0
 */

public class IteratorTest {

    @Test
    public void test1() {
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add(7);
        coll1.add(10);
        coll1.add("a");
        coll1.add(true);
        Iterator iterator = coll1.iterator();
        //hasNext(),判断是否还有下一个元素
        while (iterator.hasNext()) {
            //next(),取下一个元素的值
            System.out.print(iterator.next());//123710atrue
        }
    }

    /**
     * remove方法,移除元素去
     */
    @Test
    public void test2() {
        Collection coll1 = new ArrayList();
        coll1.add(123);
        coll1.add(7);
        coll1.add(10);
        coll1.add("a");
        coll1.add(true);
        Iterator iterator = coll1.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            if ("a".equals(obj)) {
                iterator.remove();
            }
        }
        //这里要重新赋值迭代器
        iterator = coll1.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

7.Map接口详解

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

import java.io.FileInputStream;
import java.util.*;

/**
 * @Author wfj
 * @Date 2021/6/16
 * @Description Map
 * @Version 1.0
 */

public class MapTest {
    /**
     *  一、Map: 双列数据,存储key-value对的数据
     *      --HashMap: 作为Map的主要实现类,jdk1.2出现,线程不安全的,效率高,可以存储null的key和value
     *          -- LinkedHashMap:保证在遍历map元素时,可以按照添加元素时的顺序来遍历
     *              原因:在原有的HashMap底层结构基础上,添加了一对指针,分别指向前一个元素和后一个元素,
     *              对于频繁的遍历操作,LinkedHashMap比HashMap效率高
     *      --TreeMap:保证按照添加的key-value对进行排序,实现排序遍历,此时考虑key的自然排序或者定制排序,底层使用红黑树
     *      --HashTable: 古老的实现类,jdk1.0出现,线程安全的,效率低,不可以存储null的key和value
     *          --Properties:常用来处理配置文件,key和value都是String类型
     *
     *
     *      HashMap的底层:数组+链表(jdk7及之前)
     *                    数组+链表+红黑树(jdk8)
     *
     *   面试题:
     *   1.HashMap的底层实现原理?
     *   2.HashMap和HashTable异同?
     *   3.CurrentHashMap和HashTable的异同?
     *
     *   二、Map结构的理解
     *      Map中的key:无序,不可重复的,使用Set存储所有的key ==> key所在的类要重写hasCode()方法和equals()方法
     *      Map中的value:无序,可重复的,使用Collection存储所有的value ==》 value所在的类要重写equals()方法
     *      一个键值对:key-value构成了一个Entry对象
     *      Map中的entry: 无序,不可重复的,使用Set存储所有entry
     *
     *   三、HashMap的底层原理(重点),以jdk7说
     *      HashMap map = new HashMap()
     *      在实例化以后,底层创建了长度为16的一维数组Entry[] table
     *      执行多次put操作
     *      map.put(key1,value1)
     *      首先调用key1所在的类的hashCode()方法计算key1的哈希值,此哈希值通过某种算法计算后,得到在Entry数组中存在的位置
     *      如果此位置上数据为空,此时的key1-values1则添加成功 ==情况一
     *      如果此位置上的数据不为空,(意味着此位置原本已存在一个或者多个数据(以链表方式存在)),比较key1和已存在的一个或多个数据的哈希值:
     *          如果key1的哈希值与已存在的数据的哈希值不相同,则key1-value1添加成功 ==情况二
     *          如果key1的哈希值与已存在的某一个数据(key2-value2)的哈希值相同,继续比较,调用key1所在类中的equals(key2)
     *              如果equals()返回false,此时key1-value1添加成功 ==情况三
     *              如果equals()返回true,使用value1替代value2
     *
     *       补充:关于情况二和情况三,此时key1-value1和原来的数据以链表的方法存储
     *       在不断的添加过程中,会涉及到扩容的问题,当超出临界值(且要存放的位置非空)时,要扩容,默认的扩容方式:扩容为原来容量的两倍,并将原来的数据复制过来
     *
     *       jdk8相对于jdk7在底层方面的不同
     *       1.new HashMap():底层没有数组
     *       2.jdk8底层的数组四Node[],非Entry[]
     *       3.首次调用put时,底层创建长度为16的数组
     *       4.jdk7中底层结构只有:数组+链表,jdk8中底层结构:数组+链表+红黑树
     *          当数组中的某一个位置上以链表形式存储的数据个数 > 8,且当前数组长度 > 64 时
     *          此时此索引位置上的所有数据改为红黑树存储
     *
     *      DEFAULT_INITIAL_CAPACITY: HashMap的默认容量:16
     *      DEFAULT_LOAD_FACTOR: Hash默认的加载因子:0.75,与数组利用率有关,太小的话,数组的利用率太低,太大的话,链表就可能过多了。
     *      TREEIFY_THRESHOLD: 当链表中数据大于改默认值,则转换为红黑树,值为8
     *      MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64
     *      threshold:扩容的临界值,等于容量 * 填充因子:16 * 0.75 =12
     *
     *    四、LinkedHashMap的底层实现原理,了解就好
     *          能够按照添加的顺序来遍历数据,和LinkedHashSet原理一样
     *    static class Entry<K,V> extends HashMap.Node<K,V> {
     *         Entry<K,V> before, after; //能够记录添加的元素的先后顺序
     *         Entry(int hash, K key, V value, Node<K,V> next) {
     *             super(hash, key, value, next);
     *         }
     *     }
     *
     *
     *
     */

    //基操
    @Test
    public void test1() {
        Map map = new HashMap();
        map.put(null,123);
        map.put("a","java");
        map.put("b","buso");
        map.put("c","c++");
        System.out.println(map);//{null=123, a=java, b=buso, c=c++}

        Map map1 = new LinkedHashMap();
        map1.put(null,123);
        map1.put("a","java");
        map1.put("b","buso");
        map1.put("c","c++");
        System.out.println(map1);//{null=123, a=java, b=buso, c=c++}
    }

    //map的一些常用方法
    @Test
    public void test2() {
        Map map = new HashMap();
        //put(),存数据
        //新增
        map.put("a",123);
        map.put(12,"c");
        map.put("b",5);
        //修改
        map.put("a",56);
        System.out.println(map);//{a=56, b=5, 12=c}

        //putAll(Map map)将一个map的全部数据存到另一个map里去
        Map map1 = new HashMap();
        map1.put("c",7);
        map1.put("d",8);
        map.putAll(map1);//{a=56, b=5, c=7, d=8, 12=c}
        System.out.println(map);

        //remove(Object key) 移除指定key对应的数据,并且返回数据
        Object value = map.remove("d");
        System.out.println(value);//8
        System.out.println(map);//{a=56, b=5, c=7, 12=c}


        //Object get(Object key) //获取指定key对应的value
        Object c = map.get("c");
        System.out.println(c);//7

        //boolean containsKey(Object key) 是否包含指定的key
        System.out.println(map.containsKey("d"));//true

        //boolean containsValue(Object value) 是否包含指定的value
        System.out.println(map.containsValue(8));//true

        //boolean isEmpty() 判断map的长度是否为0
        System.out.println(map.isEmpty());//false
        //获取map中key-value对的个数
        System.out.println(map.size());//4

        // boolean equals(Map map) 判断两个map的key和value是否完全一致
        System.out.println(map.equals(map1));//false

        //clear()清空数据
        map.clear();
        System.out.println(map);//{}
    }

    //map的遍历操作
    @Test
    public void test3() {
        Map map = new HashMap();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);
        map.put("e",5);

        //遍历所有的key
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        //遍历所有的value
        Collection values = map.values();
        for (Object obj : values) {
            System.out.println(obj);
        }

        //遍历所有的key和value
        //方式一:
        Set entrySet = map.entrySet();
        for (Object object : entrySet) {
            Map.Entry entry = (Map.Entry)object;
            System.out.println("键:"+entry.getKey() + "值:"+entry.getValue());
        }

        //方式二:
        Set keySet = map.keySet();
        Iterator iterator1 = keySet.iterator();
        while (iterator1.hasNext()) {
            Object next = iterator1.next();
            Object o = map.get(next);
            System.out.println("键:"+next+"值:"+o);
        }
    }

    //TreeMap的使用
    @Test
    public void test4() {
        //自然排序
        TreeMap map1 = new TreeMap();
        map1.put(new Dog("xi",13),71);
        map1.put(new Dog("bai",19),70);
        map1.put(new Dog("kai",10),78);
        map1.put(new Dog("tian",12),90);
        map1.put(new Dog("adan",11),100);
        Set keySet = map1.keySet();
        Iterator iterator1 = keySet.iterator();
        while (iterator1.hasNext()) {
            Object next = iterator1.next();
            Object o = map1.get(next);
            System.out.println("键:"+next+"值:"+o);
        }
        System.out.println("===================");
        //定制排序
        TreeMap map2 = new TreeMap(new Comparator() {
            //按照年龄从大到小排序
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Dog  && o2 instanceof Dog) {
                    Dog d1 = (Dog) o1;
                    Dog d2 = (Dog) o2;
                    return -Integer.compare(d1.getAge(),d2.getAge());
                }
                return 0;
            }
        });
        map2.put(new Dog("xi",13),71);
        map2.put(new Dog("bai",19),70);
        map2.put(new Dog("kai",10),78);
        map2.put(new Dog("tian",12),90);
        map2.put(new Dog("adan",11),100);
        Set keySet1 = map2.keySet();
        Iterator iterator2 = keySet1.iterator();
        while (iterator2.hasNext()) {
            Object next = iterator2.next();
            Object o = map2.get(next);
            System.out.println("键:"+next+"值:"+o);
        }
    }

    //Properties的使用,常用来处理配置文件,key,value都是String类型
    @Test
    public void test5() throws Exception{
        Properties properties = new Properties();
        FileInputStream fileInputStream = new FileInputStream("D://jdbc.properties");
        properties.load(fileInputStream);//加载流对应的文件
        String userName = properties.getProperty("userName");
        String password = properties.getProperty("password");
        System.out.println(userName);//root
        System.out.println(password);//123456
    }
}

jdbc.properties图
在这里插入图片描述

8.Collections工具类的常用方法

package com.yl.pdfdemo.day08.p2;

import org.junit.Test;

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

/**
 * @Author wfj
 * @Date 2021/6/21
 * @Description Collections工具类的常用方法
 * @Version 1.0
 */

public class CollectionsTest {
    /**
     * 面试题:Collection和Collections的区别?
     *  Collection是一个集合接口
     *  Collections是一个操作Collection,Map集合的工具类
     */
    @Test
    public void test1() {
        List list = new ArrayList();
        list.add(11);
        list.add(67);
        list.add(55);
        list.add(100);
        list.add(-10);
        System.out.println(list);//[11, 67, 55, 100, -10]
        //reverse()反转集合
        Collections.reverse(list);
        System.out.println(list);//[-10, 100, 55, 67, 11]

        //shuffle()对集合进行随机排序
        Collections.shuffle(list);
        System.out.println(list);//[100, -10, 67, 55, 11]

        //根据元素的自然排序对指定的list集合进行升序排序,也可以制定排序,传多一个comparator即可
        Collections.sort(list);
        System.out.println(list);//[-10, 11, 55, 67, 100]

        //swap(list,int i, int j) 交换两个指定位置的元素
        Collections.swap(list,0,1);
        System.out.println(list);//[11, -10, 55, 67, 100]

        //max(list)或者max(list,comparator) 求最大值,又或者按照制定排序求最大值
        int max = (int)Collections.max(list);
        System.out.println(max);//100

        //min(list)或者mnx(list,comparator) 求最小值,又或者按照制定排序求最小值
        int min = (int)Collections.min(list);
        System.out.println(min);//-10

        //frequency()求某个元素出现的次数
        int frequency = Collections.frequency(list, -10);
        System.out.println(frequency);//1

        //copy(list dest,list src) 将src的内容复制到dest中
        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest,list);
        System.out.println(dest);//[11, -10, 55, 67, 100]

        //replaceAll(list,Object oldVal,Object newVal) 使用新值替换旧值
        Collections.replaceAll(list,100,-100);
        System.out.println(list);//[11, -10, 55, 67, -100]

        /**
         * Collections类中提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,
         * 从而可以解决多线程并发访问集合时出现的线程安全问题
         */
        //list1是线程安全的
        List list1 = Collections.synchronizedList(list);
        System.out.println(list1);


    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值