集合框架的基础知识

时间:2021-01-21 19:23:17
集合框架的基础知识
集合与数组的区别;
     

            1:数组是固定长度的;集合可变长度的。

            2:数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。

            3:数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。

在使用一个体系时,原则:参阅顶层内容。建立底层对象。


集合框架的基础知识



ArrayList底层代码研究

集合框架的基础知识

transient关键字:

java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

ArrayList底层是一个Object数组,对于ArrayList而言,它实现List接口、底层使用数组保存所有元素,其操作基本上是对数组的操作。

LinkedList研究

集合框架的基础知识

LinkedList底层的数据结构是基于双向循环链表的,且头结点中不存放数据,既然是双向链表,那么必定存在一种数据结构——我们可以称之为节点,节点实例保存业务数据,前一个节点的位置信息和后一个节点位置信息。

集合框架的基础知识

|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。

|--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。

|--Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。


Set接口

Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器

HashSet底层源码研究

集合框架的基础知识

Hash底层是HashMap,

HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null元素。

对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。


|--TreeSet:Set集合中的元素的进行指定顺序的排序。不同步TreeSet底层的数据结构就是二叉树。

用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。

如果元素不具备比较性,在运行时会发生ClassCastException异常。

所以需要元素实现Comparable接口,强制让元素具备比较性,复写compareTo方法

依据compareTo方法的返回值,确定元素在TreeSet数据结构中的位置。

TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复,不存。

TreeSet集合排序有两种方式,Comparable和Comparator区别:

1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。

2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。

第二种方式较为灵活。

package com.inphase.collection;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;


public class ListDemo {
    
    public static void main(String[] args) {
        Set<Person> set = new TreeSet<Person>();
        set.add(new Person("张三1" , 30));
        set.add(new Person("李四2" , 24));
        set.add(new Person("张三3" , 29));
        set.add(new Person("张三4" , 28));
        set.add(new Person("张三5" , 25));
        
        Iterator< Person > iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
        
    }

}

package com.inphase.collection;

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    

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

    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int compareTo(Person o) {
        //按照年龄大小排序
        int num  = age > o.age ? 1 : age-o.age ;
        return num;
    }

    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return super.equals(obj);
    }

    @Override
    public String  toString() {
        // TODO Auto-generated method stub
        return name+"...."+age;
    }
   
}


Map集合

|--Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。

|--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable.

|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。



HashMap底层就是一个数组结构(Entry<K,V>[] table),数组中的每一项又是一个链表。
transient Entry<K,V>[] table;

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;</span>
        int hash;

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }

        public final K getKey() {
            return key;
        }

        public final V getValue() {
            return value;
        }
        .............
}

当我们往HashMapput元素的时候,先根据keyhashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

HashMapget元素时,首先计算keyhashCode,找到数组中对应位置的某一元素,然后通过keyequals方法在对应位置的链表中找到需要的元素。