JAVA_基礎集合List接口與Set接口(二)

List接口

JDK API中List接口的實現類經常使用的有:ArrayListLinkedListVectorjava

ArrayList:做爲List接口的主要實現類;線程不安全;底層使用Object[] elementData儲存。
LinkedList:對於頻繁的插入、刪除操做,使用此類效率比ArrayList高;底層使用雙向鏈表儲存。
Vector:做爲List接口的古老實現類;線程安全的;效率底;底層使用Object[] elementData儲存。算法

ArrayList的源碼分析:JDK 7
ArrayList list = new ArrayList();(底層建立了長度是10的Object[]數組elementData
list.add(123);elementData[0] = new Integer(123);
list.add(11);(若是這次的添加致使底層elementData數組容量不夠,則擴容。)
默認狀況下,擴容爲原來的容量的1.5倍,同時須要將原有數組中的數據複製到新的數組中。數組

結論:建議在開發過程當中使用帶參數的構造器:ArrayList list = new ArrayList(int capacity)安全

ArrayList的源碼分析:JDK 8ide

List接口方法

void add(int index, Object ele):在index位置插入ele元素 。
boolean addAll(int index, Collection eles):從index位置開始將eles中 的全部元素添加進來 。
Object get(int index):獲取指定index位置的元素 。
int indexOf(Object obj):返回obj在集合中首次出現的位置 。
int lastIndexOf(Object obj):返回obj在當前集合中末次出現的位置 。
Object remove(int index):移除指定index位置的元素,並返回此元素 。
Object set(int index, Object ele):設置指定index位置的元素爲ele
List subList(int fromIndex, int toIndex):返回從fromIndextoIndex 位置的子集合。源碼分析

public void test() {
        ArrayList list = new ArrayList();
        list.add(132);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom", 12));
        System.out.println(list);// [132, 456, AA, Person{name='Tom', age=12}]
        list.add(1,"BB");
        System.out.println(list);// [132, BB, 456, AA, Person{name='Tom', age=12}]
        List list1 = Arrays.asList(1, 2, 3);
        list.addAll(list1);
        System.out.println(list.size());// 8
        System.out.println(list.get(1));// BBjava
    }
public void test1() {
        ArrayList list = new ArrayList();
        list.add(132);
        list.add(456);
        list.add("AA");
        list.add(new Person("Tom", 12));
        list.add("456");
        int i = list.indexOf(456);
        System.out.println(i);// 1
        System.out.println(list.lastIndexOf("AA"));// 2
        Object remove = list.remove(0);
        System.out.println(remove);// 132
        System.out.println(list);// [456, AA, Person{name='Tom', age=12}]
        Object cc = list.set(1, "CC");
        System.out.println(cc);// AA
        System.out.println(list);// [456, CC, Person{name='Tom', age=12}]
        List subList = list.subList(2, 4);
        System.out.println(subList);// [Person{name='Tom', age=12}, 456]
        System.out.println(list);// [456, CC, Person{name='Tom', age=12}, 456]
    }
public void test3() {
        ArrayList list = new ArrayList();
        list.add(123);
        list.add(456);
        list.add("AA");
        list.add("BB");
        // 方式一:Iterator迭代器方式循環遍歷
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("*******************");
        // 方式二:forEach加強循環遍歷
        for (Object obj : list) {
            System.out.println(obj);
        }
        System.out.println("*******************");
        // 方式三:普通for循環遍歷
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

Set接口

Set接口:儲存無序的、不可重複的數據。
HashSet:做爲Set接口的主要實現類;線程不安全的;能夠儲存null值。
LinkedHashSet:做爲HashSet的子類;遍歷其內部數據時,能夠按照添加的順序遍歷。
優勢:對於頻繁的遍歷操做,LinkedHashSet效率高於HashSet
TreeSet:能夠按照添加對象的指定屬性,進行排序。this

1、儲存無序、不可重複:(以HashSet爲例說明)線程

  1. Set無序性:不等於隨機性。存儲的數據在底層數組中並不是按照數組索引的順序添加。而是根據數據的哈希值決定的。
  2. Set不可重複性:保證添加的元素按照equals()判斷時,不能返回true。即:相同的元素只能添加一個。

2、添加元素的過程:(以HashSet爲例說明)code

  1. 咱們向HashSet中添加元素a,首先調用元素a所在類的hashCode()方法,計算元素a的哈希值,此哈希值接着經過某種算法出生在HashSet底層數組中的位置(即爲:索引位置)。
    數組此位置上是否已經有元素:
    若是有此位置上沒有其它元素,則元素a添加成功。→狀況1
    若是此位置上有其它元素B(或以鏈表形式存在的多個元素),則比較元素a與元素b的hash值:
    若是hash值不相同,則元素a添加成功。→狀況2
    若是hash值相同,進而須要調用元素a所在類的equlas()方法:
    equlas()返回true,元素a添加失敗。
    equlas()返回false,則元素a添加成功。→狀況3
    對於添加成功的狀況2和狀況3而言:元素a與已經存在指定索引位置上數據以鏈表的方式儲存。
    JDK 7:元素a放到數組中,指向原來的元素。
    JDK 8:原來的元素在數組中,指向元素a。
    總結:七上八下對象

    HashSet底層:數組+鏈表的結構。

    要求:向Set中添加的數據,其所在的類必定要重寫hashCode()equlas()
    要求:重寫的hashCode()equlas()儘量的保持一致性:相等的對象必須具備相等的散列碼(hash值)。

    public void test() {
            Set set = new HashSet();
            set.add(456);
            set.add(123);
            set.add("AA");
            set.add("CC");
            set.add(new User("Tom",20));
            set.add(new User("Tom",20));
            set.add(new User("Jerry",19));
            set.add("DD");
            Iterator iterator = set.iterator();
            while(iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    public class User {
        private String name;
        private int age;
    	...
        @Override
        public String toString() {
    		...
        }
        @Override
        public boolean equals(Object o) {
            System.out.println("User equals()...");
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            User user = (User) o;
    
            if (age != user.age) return false;
            return name != null ? name.equals(user.name) : user.name == null;
        }
        @Override
        public int hashCode() {
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + age;
            return result;
        }
    }

3、LinkedHashSet的使用

LinkedHashSet做爲HashSet的子類,在添加數據的同時,每一個數據還維護了兩個引用,記錄此數據前一個數據和後一個數據。
​ 優勢:對於頻繁的遍歷操做,LinkedHashSet效率高於HashSet

public void test2() {
        Set set = new LinkedHashSet();
        set.add(456);
        set.add(123);
        set.add("AA");
        set.add("CC");
        set.add(new User("Tom",20));
        set.add(new User("Tom",20));
        set.add(new User("Jerry",19));
        set.add("DD");

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

4、TreeSet的使用

  1. TreeSet中添加的數據,要求是相同類的對象。
    失敗:不能添加不一樣類的對象

    set.add(123);
    set.add("AA");
    set.add(new User("Tom",20));
  2. 兩種排序方式:天然排序(實現Comparable接口) 和 定製排序(Comparator

    天然排序中,比較兩個對象是否行同的標準爲:compareTo()返回0,再也不是equlas()

    public void test1() {
            TreeSet set = new TreeSet();
            // 舉例一:
    //        set.add(123);
    //        set.add(456);
    //        set.add(-487);
    //        set.add(9);
            // 舉例二:
    //        set.add("AA");
    //        set.add("DD");
    //        set.add("BB");
    //        set.add("ABC");
            // 舉例三:
            set.add(new User("Tom",22));
            set.add(new User("Jerry",22));
            set.add(new User("Jim",20));
            set.add(new User("Mike",54));
            set.add(new User("Jack",58));
            set.add(new User("Jack",20));
            Iterator iterator = set.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
    public class User implements Comparable {
        private String name;
        private int age;
        @Override
        public String toString() {...}
        @Override
        public boolean equals(Object o) {...}
        @Override
        public int hashCode() {...}
        // 按照姓名從小到大排序,年齡從小到大排序
        @Override
        public int compareTo(Object o) {
            if (o instanceof User) {
                User user = (User) o;
                int compare = user.name.compareTo(this.name);
                if (compare != 0) {
                    return compare;
                }else {
                    return Integer.compare(this.age,user.age);
                }
            }else {
                throw new RuntimeException("當前傳遞的類型不匹配");
            }
        }
    }

    定製排序中,比較兩個對象是否行同的標準爲:compare()返回0,再也不是equlas()

    public void test2() {
            Comparator comparator = new Comparator() {
                // 按照年齡從小到大排序
                @Override
                public int compare(Object o1, Object o2) {
                    if (o1 instanceof User && o2 instanceof User) {
                        User user1 = (User) o1;
                        User user2 = (User) o2;
                        return Integer.compare(user1.getAge(),user2.getAge());
                    }else {
                        throw new RuntimeException("傳入的類型不匹配");
                    }
                }
            };
            TreeSet set = new TreeSet(comparator);
            set.add(new User("Tom",22));
            set.add(new User("Jerry",21));
            set.add(new User("Jim",20));
            set.add(new User("Mike",54));
            set.add(new User("Mary",54));
            set.add(new User("Jack",58));
            set.add(new User("Jack",20));
            Iterator iterator = set.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
        }
相關文章
相關標籤/搜索