Java集合框架详解

Java集合框架详解

集合的概念

  • 概念:对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能

  • 和数组区别:

    • (1)数组长度固定,集合长度不固定
    • (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
  • 位置:Java.util.*

Collection体系

![](/Users/apple/Desktop/截屏2021-02-22 下午2.47.24.png)

Collection接口

  • 特点:代表一组任意类型的对象,无序、无下标、不能重复
  • 方法:
    • boolean add(Object obj)//添加一个对象
    • boolean addAll(Collection c) //将一个集合中的所有对象添加到此集合中
    • void clear() //清空此集合中的所有对象
    • boolean contains(Object o) //检查此集合中是否包含o对象
    • boolean equals(Object o) //比较此集合是否与指定对象相等
    • boolean isEmpty() //判断此集合是否为空
    • boolean remove(Object o ) //在此集合中移除o对象
    • int size () //返回此集合中的元素个数
    • Object[ ] toArray() //将此集合转换成数组

Collection使用(1)

代码片段如下:

/*Collection接口的使用
 *(1)添加元素
 * (2)删除元素
 * (3)遍历元素
 * (4)判断
 * */
public class Demo01 {
    public static void main(String[] args) {
//        创建集合
        Collection collection = new ArrayList();
//        *(1)添加元素
        collection.add("苹果");
        collection.add("西瓜");
        collection.add("榴莲");
        System.out.println("元素个数" + collection.size());
        System.out.println(collection);
//         * (2)删除元素
        collection.remove("榴莲");
        System.out.println("删除之后"+collection.size());
//         * (3)遍历元素【重点】
        //3.1使用增强for
        System.out.println("-------3.2使用增强for-------");
        for (Object object : collection) {
            System.out.println(object);
        }
        //3.2使用迭代器(迭代器专门用来遍历集合的一种方式)
        //hasNext();有没有下一个元素
        //next();获取下一个元素
        //remove();删除当前元素
        System.out.println("-------3.2使用增强for-------");
        Iterator it = collection.iterator();
        while (it.hasNext()) {
            String s = (String)it.next();
            System.out.println(s);
//            collection.remove(s);并发修改异常
            it.remove();
        }
        System.out.println("元素个数:" + collection.size());
//         * (4)判断
        System.out.println(collection.contains("西瓜"));
        System.out.println(collection.isEmpty());
    }
}

Collection使用(2)

代码片段如下:

/*
* Collection保存学生信息
* */
public class Demo02 {
    public static void main(String[] args) {
//        新建Collection对象
        Collection collection = new ArrayList();
        Student s1 = new Student("张三", 20);
        Student s2 = new Student("张无忌", 18);
        Student s3 = new Student("王二", 22);
//        1.添加数据
        collection.add(s1);
        collection.add(s2);
        collection.add(s3);
        System.out.println("元素个数" + collection.size());
        System.out.println(collection.toString());
//        2.删除
        collection.remove(s1);
//        collection.clear();
        System.out.println("删除之后:" + collection.size());
//        3.遍历
//        3.1增强for
        System.out.println("-----------增强for--------");
        for (Object object : collection) {
            Student s = (Student) object;
            System.out.println(s.toString());

        }
//        3.2迭代器:hasNext() next() remove(),迭代过程中不能使用collection的删除方法
        System.out.println("-----------迭代器--------");
        Iterator it = collection.iterator();
        while (it.hasNext()) {
            Student s = (Student)it.next();
            System.out.println(s.toString());
        }
//        4判断
        System.out.println(collection.contains(s1));
        System.out.println(collection.isEmpty());
    }
}

List子接口

  • 特点:有序、有下标、元素可以重复
  • 方法:
    • void add(int index,Object o)//在index位置插入对象o
    • boolean addAll(int index,Collection c)//将一个集合中的元素添加到此集合中的index位置
    • Object get(int index)//返回集合中指定位置的元素
    • List subList(int fromIndex, int toIndex)//返回fromIndex和toIndex之间的集合元素

List接口使用(1)

代码片段如下:

/*
* List子接口的使用
* 特点:1 有序 有下标 2 可以重复*/
public class Demo03 {
    public static void main(String[] args) {
//     先创建集合对象
        List list = new ArrayList<>();
//        1添加元素
        list.add("苹果");
        list.add("小米");
        list.add(0,"华为");
        System.out.println("元素个数" + list.size());
        System.out.println(list.toString());
//        2删除元素
//        list.remove("苹果");
//        list.remove(0);
//        System.out.println("删除之后:" + list.size());
//        System.out.println(list.toString());
//        遍历
//        3.1使用for遍历
        System.out.println("------3.1使用for遍历-------");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
//        3.2使用增强for
        System.out.println("------3.2使用增强for-------");
        for (Object object : list) {
            System.out.println(object);
        }
//        3.3使用迭代器
        System.out.println("------3.3使用迭代器-------");
        Iterator it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//        3.4使用列表迭代器,和Iterator的区别,ListIterator可以向前或向后遍历,添加、删除、修改元素
        ListIterator lit = list.listIterator();
        System.out.println("-----------3.4使用列表迭代器从前往后----------");
        while (lit.hasNext()) {
            System.out.println(lit.nextIndex()+":"+lit.next());

        }
        System.out.println("-----------3.4使用列表迭代器从后往前----------");
        while (lit.hasPrevious()) {
            System.out.println(lit.previousIndex()+":"+lit.previous());

        }
//      4判断
        System.out.println(list.contains("苹果"));
        System.out.println(list.isEmpty());
//        5获取位置
        System.out.println(list.indexOf("华为"));
    }

}

LIst接口使用(2)

代码片段如下:

/**
 * @author Amuese
 * @create 2021-02-23-上午10:43
 */
/*
* List的使用*/
public class Demo04 {
    public static void main(String[] args) {
//        创建集合
        List list = new ArrayList();
//        添加数字数据(自动装箱)
        list.add(20);
        list.add(30);
        list.add(40);
        list.add(50);
        list.add(60);
        System.out.println("元素个数" + list.size());
        System.out.println(list.toString());
//       2删除操作
//        list.remove(0);
        list.remove(new Integer(20));
        System.out.println("删除元素:" + list.size());
        System.out.println(list.toString());

//        3补充方法subList,返回子集合
        List subList = list.subList(1, 3);
        System.out.println(subList.toString());


    }
}

List实现类

  • ArrayLIst【重点】
    • 数组结构实现,查询快、增删慢;
    • JDK1.2版本,运行效率快、线程不安全
  • Vector:
    • 数组结构实现,查询快、增删慢
    • JDK1.0版本,运行效率慢、线程安全
  • LinkedList:
    • 链表结构实现,增删快,查询慢

代码片段如下:

  • 注意:能用new 新的对象去操作去比较是因为重写了equals方法,在没有重写以前,比较的都是地址了
/*
* ArrayList的使用
* 存储结构:数组,查找遍历速度快,增删慢
*
* */
public class Demo05 {
    public static void main(String[] args) {
//        创建集合 size 0 容量 0
        ArrayList arrayList = new ArrayList<>();
//        1添加元素
        Student s1 = new Student("刘德华", 20);
        Student s2 = new Student("郭富城", 22);
        Student s3 = new Student("梁朝伟", 18);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        System.out.println("元素个数" + arrayList.size());
        System.out.println(arrayList.toString());
//        2删除元素
//        arrayList.remove(s1);
        arrayList.remove(new Student("刘德华",20));
        System.out.println("删除之后:" + arrayList.toString());
//        3遍历元素【重点】
//            3.1使用迭代器
        System.out.println("---------3.1使用迭代器------------");
        Iterator it = arrayList.iterator();
        while (it.hasNext()) {
            Student s = (Student)it.next();
            System.out.println(s.toString());
        }
//        3.2列表迭代器
        ListIterator lit = arrayList.listIterator();
        System.out.println("---------3.2使用列表迭代器------------");
        while (lit.hasNext()) {
            Student s = (Student)lit.next();
            System.out.println(s.toString());
        }
        System.out.println("---------3.2使用列表迭代器逆序------------");
        while (lit.hasPrevious()) {
            Student s = (Student) lit.previous();
            System.out.println(s.toString());
        }
//        4判断
        System.out.println(arrayList.contains(new Student("郭富城", 22)));
        System.out.println(arrayList.isEmpty());
//        5查找
        System.out.println(arrayList.indexOf(s1));
    }
}

ArrayList源码分析

ArrayList

  • 源码分析:
    • 默认容量大小 DEFAULT_CAPACITY = 10;
    • 注意:如果你没有向集合中添加任何元素,容量0,添加一个元素之后 容量10,每次扩容大小都是之前的1.5倍
    • 存放元素的数组 transient Object[] elementData;
    • size 实际元素个数
    • add() 添加元素
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
        }
private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Vector使用

代码片段如下

//演示Vector集合的使用
//    存储结构:数组
public class Demo06 {
    public static void main(String[] args) {
//        创建集合
        Vector vector = new Vector<>();
//        1添加元素
        vector.add("草莓");
        vector.add("芒果");
        vector.add("西瓜");
        System.out.println("元素个数" + vector.size());
//        2删除
//        vector.remove(0);
//        vector.remove("西瓜");
//        vector.clear();
//        3遍历
//        使用枚举器
        Enumeration en = vector.elements();
        while (en.hasMoreElements()) {
            String o = (String)en.nextElement();
            System.out.println(o);
        }
//        4判断
        System.out.println(vector.contains("西瓜"));
        System.out.println(vector.isEmpty());
//        5vector其他方法
//        firstElement、lastElement、elementAt()

    }
}

LinkedList使用

代码片段如下:

//LinkedList的使用
//    存储结构:双向链表
public class Demo07 {
    public static void main(String[] args) {
//        创建集合
        LinkedList linkedList = new LinkedList();
        //        1添加元素
        Student s1 = new Student("刘德华", 20);
        Student s2 = new Student("郭富城", 22);
        Student s3 = new Student("梁朝伟", 18);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        System.out.println("元素个数" + linkedList.size());
        System.out.println(linkedList.toString());
//        2删除
//        linkedList.remove(s1);
//        System.out.println("删除之后:" + linkedList.size());
//        linkedList.clear();
//        3遍历
//        3.1for遍历
        System.out.println("----------for--------");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
//        3.2增强for
        System.out.println("----------增强for--------");
        for (Object o : linkedList) {
            Student o1 = (Student) o;
            System.out.println(o1);
        }
//        3.3使用迭代器
        System.out.println("-----------使用迭代器---------");
        Iterator it = linkedList.iterator();
        System.out.println(s1.toString());
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
        //        3.3使用列表迭代器
        System.out.println("-----------列表使用迭代器---------");
        ListIterator lit = linkedList.listIterator();
        while (lit.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.toString());
        }
//        4判断
        System.out.println(linkedList.contains(s1));
        System.out.println(linkedList.isEmpty());
//          5获取
        System.out.println(linkedList.indexOf(s1));

    }
}

LInkedList源码分析

代码片段如下:

//链表的形成
private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

ArrayList和LinkedLIst区别

图片

泛型概述

  • Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递
  • 常见形式有泛型类、泛型接口、泛型方法
  • 语法:
    • <T,...> T称为类型占位符,表示一种引用类型
  • 好处:
    • (1)提高代码的重用性
    • (2)防止类型转换异常,提高代码的安全性

泛型类

  • 简单点说就是可以自己定义他到底是什么引用类型,然后定义好了自己的引用类型之后就可以用这些引用类型的方法

代码片段如下:

泛型类

//泛型类
//    语法:类名<T>
//    T表示占位符,表示一种引用类型,如果编写多个使用逗号隔开
public class MyGeneric<T> {
//    使用泛型T
//    1创建变量
    T t;
//    2作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
//    泛型作为方法的返回值
    public T getT(){
        return t;
    }
}

控制台

public class TestGeneric {
    public static void main(String[] args) {
//        使用泛型类创建对象
//        注意:1泛型只能使用引用类型,2不同泛型类型对象之间不能相会赋值
        MyGeneric<String> myGeneric = new MyGeneric<String>();
        myGeneric.t="hello";
        myGeneric.show("大家好,加油");
        String string = myGeneric.getT();
        MyGeneric<Integer> myGeneric2 = new MyGeneric<>();
        myGeneric2.t=100;
        myGeneric2.show(200);
        Integer integer = myGeneric2.getT();


    }
}

泛型接口

代码片段如下

泛型接口

/*
 *泛型接口
 *语法:接口名<T>
 *注意:不能泛型静态常量
 *  */
public interface MyInterface<T> {
    String name= "张三";
    T serve(T t);
}

实现接口的类

public class MyInterfaceImpl implements MyInterface<String> {
    @Override
    public String serve(String s) {
        System.out.println(s);
        return s;
    }
}

实现接口的泛型类

public class MyInterfaceImpl2<T> implements MyInterface<T> {
    @Override
    public T serve(T t) {
        System.out.println(t);
        return t;
    }
}

控制台

MyInterfaceImpl impl = new MyInterfaceImpl();
        impl.serve("son");

        MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<>();
        impl2.serve(1000);

泛型方法

代码片段如下:

/*
 *泛型方法
 *语法:<T>返回值类型 */
public class MyGenericMethod {
//    泛型方法
    public <T> T show(T t){
        System.out.println("泛型方法"+t);
        return t;
    }

}


控制台

//        泛型方法
        MyGenericMethod myGenericMethod = new MyGenericMethod();
        //方法的类型是由传进的类型决定
        myGenericMethod.show("中国加油");

泛型集合

  • 概念:参数化类型、类型安全的集合,强制集合元素的类型必须一致
  • 特点:
    • 编译时即可检查,而非运行时抛出异常
    • 访问时,不必类型转换(拆箱)
    • 不同泛型之间引用不能相互赋值,泛型不存在多态
public class Demo03 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("xxx");
        arrayList.add("yyy");
//        arrayList.add(10);
//        arrayList.add(20);
        for (String s : arrayList) {
            System.out.println(s);
        }

        ArrayList<Student> arrayList2 = new ArrayList<>();
        Student s1 = new Student("刘德华", 20);
        Student s2 = new Student("郭富城", 20);
        Student s3 = new Student("梁潮位", 20);
        arrayList2.add(s1);
        arrayList2.add(s2);
        arrayList2.add(s3);

        Iterator<Student> iterator = arrayList2.iterator();
        while (iterator.hasNext()) {
            Student s = iterator.next();
            System.out.println(s.toString());
        }
//        不同的泛型之间不能相互赋值
//        arrayList2=arrayList;
    }
}

Set集合概述

Set子接口

  • 特点:无序、无下标、元素不可重复
  • 方法:全部继承自Collection中的方法

Set接口使用

代码片段如下:

//测试Set接口的使用
//    特点:(1)无序、没有下标(2)不能重复
public class Demo04 {
    public static void main(String[] args) {
//        创建集合
        HashSet<String> set = new HashSet<>();
//        1添加数据
        set.add("苹果");
        set.add("华为");
        set.add("小米");
//        set.add("华为");
        System.out.println("数据个数" + set.size());
        System.out.println(set.toString());
//        2删除数据
//        set.remove("小米");
//        System.out.println(set.toString());
//        3遍历【重点】
//        3.1使用增强for
        System.out.println("--------增强for-------");
        for (String string : set) {
            System.out.println(string);
        }
//        3.2使用迭代器
        System.out.println("--------使用迭代器-------");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//        4判断
        System.out.println(set.contains("华为"));
        System.out.println(set.isEmpty());
    }
}

HashSet使用(1)

Set实现类

  • HashSet【重点】:
    • 基于HashCode计算存放位置
    • 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
  • TreeSet:
    • 基于排列顺序实现元素不重复
/*
 *HashSet集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * */
public class Demo05 {
    public static void main(String[] args) {
//        新建集合
        HashSet<String> hashSet = new HashSet<>();
//        1添加元素
        hashSet.add("刘德华");
        hashSet.add("梁朝伟");
        hashSet.add("林志玲");
        hashSet.add("周润发");
//        hashSet.add("刘德华");
        System.out.println("元素个数" + hashSet.size());
        System.out.println(hashSet.toString());
//        2删除数据
//        hashSet.remove("刘德华");
//        System.out.println("删除之后:" + hashSet.size());
//        3遍历操作
//        3.1增强for
        System.out.println("--------3.1增强for--------");
        for (String s : hashSet) {
            System.out.println(s);
        }
        //        3.2使用迭代器
        System.out.println("--------3.2迭代器--------");
        Iterator<String> it = hashSet.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//          4判断
        System.out.println(hashSet.contains("郭富城"));
        System.out.println(hashSet.isEmpty());
    }
}

HashSet使用(2)

代码片段如下:

/*HashSet的使用
* */
public class Demo06 {
    public static void main(String[] args) {
//        创建集合
        HashSet<Person> peoples = new HashSet<>();
//        添加数据
        Person p1 = new Person("刘德华", 20);
        Person p2 = new Person("林志玲", 22);
        Person p3 = new Person("梁朝伟", 25);
        peoples.add(p1);
        peoples.add(p2);
        peoples.add(p3);
         
        System.out.println("元素个数:" + peoples.size());
        System.out.println(peoples.toString());

    }
}

HashSet存储方式

代码片段如下:

/*HashSet的使用
* 存储结构:哈希表(数组+链表+红黑树)
* 存储过程
* (1)根据hashcode计算保存位置,如果此位置为空,则直接保存,如果不为空执行第二步
* (2)在执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
* */
public class Demo06 {
    public static void main(String[] args) {
//        创建集合
        HashSet<Person> peoples = new HashSet<>();
//        添加数据
        Person p1 = new Person("刘德华", 20);
        Person p2 = new Person("林志玲", 22);
        Person p3 = new Person("梁朝伟", 25);
        peoples.add(p1);
        peoples.add(p2);
        peoples.add(p3);
//        不会认为是重复,还是会重复添加,因为比的是哈希值和地址,所以如果要避免重复
//        添加,就要重写hashcode方法和equals方法
        peoples.add(new Person("梁朝伟", 25) );
        System.out.println("元素个数:" + peoples.size());
        System.out.println(peoples.toString());
//      2删除操作
//        peoples.remove(p1);
//        因为重写了hashcode和equals,所以可以删除
//        peoples.remove(new Person("刘德华", 20));
//        System.out.println("删除之后:" + peoples.size());
//        3遍历【重点】
//        3.1使用增强for
        for (Person person : peoples) {
            System.out.println(person.toString());
        }
//        3.2迭代器
        Iterator<Person> it = peoples.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//        4判断
        System.out.println(peoples.contains(p1));
        System.out.println(peoples.isEmpty());

    }
}

Person方法重写

    @Override
    public int hashCode() {
        int n1=this.name.hashCode();
        int n2=this.age;
        return n1+n2;
    }


    @Override
    public boolean equals(Object obj) {

        if (this==obj) {
            return true;
        }
        if (obj==null) {
            return false;
        }
        if (obj instanceof Person) {
            Person p=(Person)obj;
            if (this.name.equals(p.getName())&&this.age==p.getAge()){
                return true;
            }
        }
        return false;
    }


HashSet方法补充

为什么重写hashcode方法需要加一个31呢

  1. 31是一个质数,减少散列冲突
  2. 31提高执行效率,31*i=(i<<5)-i

TreeSet概述

  • HashSet【重点】
    • 基于HashCode计算元素存放位置
    • 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
  • TreeSet:
    • 基于排列顺序实现元素不重复
    • 实现了SortedSet接口,对集合元素自动排序
    • 元素对象的类型必须实现Comparable接口,指定排序规则
    • 通过CompareTo方法确定是否为重复元素

TreeSet使用

代码片段如下:

/*TreeSet的使用
* 存储结构:红黑树
* */
public class Demo07 {
    public static void main(String[] args) {
//        创建集合
        TreeSet<String> treeSet = new TreeSet<>();
//        1添加元素
        treeSet.add("xyz");
        treeSet.add("abc");
        treeSet.add("hello");
        treeSet.add("xyz");
        System.out.println("元素个数:" + treeSet.size());
        System.out.println(treeSet.toString());
//        2删除
//        treeSet.remove("xyz");
//        System.out.println("删除之后:" + treeSet.size());
//        3遍历
//        3.1使用增强for
        for (String s : treeSet) {
            System.out.println(s);
        }
//        3.2使用迭代器
        Iterator<String> it = treeSet.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//        4判断
        System.out.println(treeSet.contains("abc"));
    }
}

/*
 *使用TreeSet保存数据
 * 存储结构:红黑树
 *要求:元素必须要实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
 * */
public class Demo08 {
    public static void main(String[] args) {
//        创建集合
        TreeSet<Person> persons = new TreeSet<>();
//        1添加元素
        Person p1 = new Person("刘德华", 20);
        Person p2 = new Person("林志玲", 22);
        Person p3 = new Person("梁朝伟", 25);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        System.out.println("元素个数:" + persons.size());
        System.out.println(persons.toString());
//        2删除
//        persons.remove(p1);
//        System.out.println(persons.size());
        //        3遍历
//        3.1使用增强for
        for (Person s : persons) {
            System.out.println(s);
        }
//        3.2使用迭代器
        Iterator<Person> it = persons.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
//        4判断
        System.out.println(persons.contains("abc"));
    }
}

Person类继承Comparable接口的方法

//    先按姓名来比,然后再按年龄比
    @Override
    public int compareTo(Object o) {
        Person o1 = (Person) o;
        int n1 =this.getName().compareTo(o1.getName());
        int n2 =this.age-o1.getAge();

        return n1==0?n2:n1;
    }

Comparator接口

/*
 *TreeSet集合的使用
 * comparator:实现定制比较(比较器)
 * comparable:可比较的
 * */
public class Demo09 {
    public static void main(String[] args) {
//        创建集合,并指定比较规则
        TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int n1 = o1.getAge() - o2.getAge();
                int n2 = o1.getName().compareTo(o2.getName());

                return n1 == 0 ? n2 : n1;
            }
        });
        Person p1 = new Person("xyz", 20);
        Person p2 = new Person("hello", 22);
        Person p3 = new Person("zhangsan", 25);
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        System.out.println("元素个数:" + persons.size());
    }
}

TreeSet案例

/*
 *要求:使用TreeSet集合实现字符串按照长度进行排序
 * helloworld  zhang  c wangwu beijing xian nanjing
 * Comparator接口实现定制比较
 * */
public class Demo10 {
    public static void main(String[] args) {
//        创建集合,并指定规则
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 =o1.length()-o2.length();
                int n2 =o2.compareTo(o2);
                return n1==0?n2:n1;
            }
        });
//        添加数据
        treeSet.add("helloworld");
        treeSet.add("zhang");
        treeSet.add("zhang");
        treeSet.add("beijing");
        treeSet.add("xian");
        treeSet.add("nanjing");
        System.out.println(treeSet.toString());


    }
}

Map集合

Map父接口

  • 特点:存储一对数据(Key-Value),无序、无下标,键不可重复,值可重复
  • 方法:
    • V put(K key,V value)//将对象存入到集合中,关联键值。key重复则覆盖原值
    • Object get(Object key)//根据键获取对应的值
    • Set//返回所有key
    • Collection //键值匹配到Set集合

Map接口使用

代码片段如下:

/*Map接口的使用
 *特点:(1)存储键值对  (2)键不能重复,值可以重复(3)无序
 *
 * */
public class Demo01 {
    public static void main(String[] args) {
//        创建Map集合
        HashMap<String, String> map = new HashMap<>();
//        1添加元素
        map.put("cn","中国");
        map.put("uk","英国");
        map.put("usa","美国");
        System.out.println("元素个数:" + map.size());
        System.out.println(map.toString());
//        2删除
//        map.remove("usa");
//        System.out.println("删除之后:" + map.size());
//        3遍历
//        3.1使用keySet()
        System.out.println("---------keySet()-----------");
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            System.out.println(key+"-------"+map.get(key));
        }
//        3.2使用entrySet()方法
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey() + "---------" + entry.getValue());
        }
//        4判断
        System.out.println(map.containsKey("ch"));
        System.out.println(map.containsValue("泰国"));
    }
}

HashMap的使用(1)

  • JDK1.2版本,线程不安全,运行效率块;允许用null 作为key或是value
  • 构造方法构造一个具有默认初始容量(16)和默认加载因子(0.75)的空HashMap

代码片段如下:

/*
 *HashMap集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 使用key的hashcode和equals作为重复
 * */
public class Demo02 {
    public static void main(String[] args) {
//        创建集合
        HashMap<Student, String> student = new HashMap<>();
//        添加元素
        Student s1 = new Student("孙悟空", 100);
        Student s2 = new Student("猪八戒", 101);
        Student s3 = new Student("沙和尚", 102);
        student.put(s1,"北京");
        student.put(s2,"上海");
        student.put(s3,"杭州");
//        能被录入
        student.put(new Student("沙和尚",102),"南京");
        System.out.println("元素个数:" + student.size());
        System.out.println(student.toString());
//        2删除
        student.remove(s1);
        System.out.println("删除之后" + student.size());
//        3遍历
//        3.1使用keySet()
        System.out.println("------------keySet---------");
        for (Student key : student.keySet()) {
            System.out.println(key.toString() + "========="+student.get(key));
        }
        System.out.println("------------entrySet---------");
//        3.2使用entrySet()
        for (Map.Entry<Student, String> entry : student.entrySet()) {
            System.out.println(entry.getKey()+"----------"+entry.getValue());
        }
//        4判断
        System.out.println(student.containsKey(s1));
    }
}

HashMap源码分析

代码片段如下:

属性

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//hashMap初始容量大小
static final int MAXIMUM_CAPACITY = 1 << 30;//hashmap的数组最大容量
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
static final int TREEIFY_THRESHOLD = 8;//jdk1.8当链表长度大于8时,调整成红黑数
static final int UNTREEIFY_THRESHOLD = 6;//jdk1.8当链表长度小于6时,调整成链表
static final int MIN_TREEIFY_CAPACITY = 64;//jdk1.8 当链表长度大于8时,并且集合元素个数大于等于64时,调整成红黑树
transient Node<K,V>[] table;//哈希表中的数组
transient int size;//元素个数  

无参构造

    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }

put方法

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

总结:

  1. HashMap刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
  2. 当元素个数大于阀值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
  3. jdk1.8 当每个链表长度大于8,并且元素个数大于等于64时,会调整为红黑树,目的提高执行效率
  4. Jdk1.8 当链表长度小于6时,调整成链表
  5. jdk1.8以前,链表时头插入,jdk1.8以后时是尾插入

Hashtable和Properties

  • HashMap【重点】
    • JDK1.2版本,线程不安全,运行效率快;允许用null 作为key或是value
  • Hashtable
    • JDK1.0版本,线程安全,运行效率慢;不允许null作为key或是value
  • Properties
    • Hashtable的子类,要求key和value都是String。通常用于配置文件的读取

TreeMap的使用

  • HashMap【重点】
    • 实现了SortedMap接口(是Map的子接口),可以对key自动排序

代码片段如下:

public class Demo03 {
    public static void main(String[] args) {
//       新建集合
        TreeMap<Student, String> treeMap = new TreeMap<>();
//        1添加元素
        Student s1 = new Student("孙悟空", 100);
        Student s2 = new Student("猪八戒", 101);
        Student s3 = new Student("沙和尚", 102);
        treeMap.put(s1,"北京");
        treeMap.put(s1,"上海");
        treeMap.put(s1,"深圳");
        System.out.println("元素个数:" + treeMap.size());
        System.out.println(treeMap.toString());
//        2删除
        treeMap.remove(s3);
        System.out.println(treeMap.size());
//        3遍历
//        3.1使用keySet()
        System.out.println("------------keySet---------");
        for (Student key : treeMap.keySet()) {
            System.out.println(key.toString() + "========="+treeMap.get(key));
        }
        System.out.println("------------entrySet---------");
//        3.2使用entrySet()
        for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey()+"----------"+entry.getValue());
        }
//        4判断
        System.out.println(treeMap.containsKey(s1));
    }
}

Colletions工具类

  • 概念:集合工具类,定义了除了存取以为的集合常用方法
  • 方法:
    • public static void reverse(List<?> list) //反转集合中元素的顺序
    • public static void shuffle(List<?> list) //随机重置集合元素的顺序
    • Public static void sort(List list) //升序排序(元素类型必须实现Comparable接口)

代码片段如下:

public class Demo04 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(20);
        list.add(5);
        list.add(12);
        list.add(10);
        list.add(30);
        list.add(6);
//        sort排序
        System.out.println("排序之前:" + list.toString());
        Collections.sort(list);
        System.out.println("排序之前" + list.toString());
//        binarySearch二分查找
        int i = Collections.binarySearch(list, 13);
        System.out.println(i);
//        copy复制
        ArrayList<Integer> dest = new ArrayList<>();
        for (int j = 0; j < list.size(); j++) {
            dest.add(0);
        }
        Collections.copy(dest,list);
        System.out.println(dest.toString());
//        reversefanz
        Collections.reverse(list);
        System.out.println("反转之后:" + list);
//        shuffle 打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:" + list);
//        补充:list转成数组
        Integer[] arr = list.toArray(new Integer[0]);
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));
//        数组转成集合
        String[] names= {"张三","李四","王五"};
        List<String> list2 = Arrays.asList(names);
//        集合是一个受限集合,不能添加和删除
        System.out.println(list2);
//        把基本类型数组转成集合时,需要修改为包装类
        int[] nums= {100,200,300,400,500};
        List<int[]> list3 = Arrays.asList(nums);

    }
}

posted @ 2021-02-26 16:53  武藤游戏_ov  阅读(22)  评论(0)    收藏  举报