Java中的集合(上)

第11章 集合

本章學習目標

  • 知道集合與數(shù)組的區(qū)別
  • 掌握Collection接口的常用方法
  • 理解HashSet、LinkedHashSet、TreeSet的區(qū)別
  • 理解Set與List集合的區(qū)別
  • 掌握List接口的常用方法
  • 理解Vector和ArrayList的區(qū)別
  • 理解ArrayList與LinkedList的區(qū)別
  • 掌握Queue和Deque隊列接口的常用方法
  • 掌握棧和隊列的區(qū)別
  • 知道Collection集合與Map集合的區(qū)別
  • 掌握Map接口的常用方法
  • 掌握Hashtable與HashMap的區(qū)別
  • 掌握LinkedHashMap、TreeMap、Properties的區(qū)別
  • 了解Set與Map之間的關(guān)系
  • 掌握集合工具類Collections的常用方法
  • 掌握數(shù)組與List集合之間的轉(zhuǎn)換
  • 掌握集合框架關(guān)系圖

11.1 Collection集合

11.1.1 集合的概念

集合是java中提供的一種容器,可以用來存儲多個數(shù)據(jù)。

集合和數(shù)組既然都是容器,它們有啥區(qū)別呢?

  • 數(shù)組的長度是固定的。集合的長度是可變的。
  • 數(shù)組中可以存儲基本數(shù)據(jù)類型值,也可以存儲對象,而集合中只能存儲對象

集合主要分為兩大系列:Collection和Map,Collection 表示一組對象,Map表示一組映射關(guān)系或鍵值對。

11.1.2 Collection<E>接口

Collection 層次結(jié)構(gòu)中的根接口。Collection 表示一組對象,這些對象也稱為 collection 的元素。一些 collection 允許有重復(fù)的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無序的。JDK 不提供此接口的任何直接實現(xiàn):它提供更具體的子接口(如 Set 和 List、Queue)實現(xiàn)。此接口通常用來傳遞 collection,并在需要最大普遍性的地方操作這些 collection。

Collection<E>是所有單列集合的父接口,因此在Collection中定義了單列集合(List和Set)通用的一些方法,這些方法可用于操作所有的單列集合。方法如下:

1、添加元素

  • (1)add(E obj):添加元素對象到當前集合中
  • (2)addAll(Collection<? extends E> other):添加other集合中的所有元素對象到當前集合中,即this = this ∪ other

2、刪除元素

  • (1) boolean remove(Object obj) :從當前集合中刪除第一個找到的與obj對象equals返回true的元素。
  • (2)boolean removeAll(Collection<?> coll):從當前集合中刪除所有與coll集合中相同的元素。即this = this - this ∩ coll
  • (3)boolean retainAll(Collection<?> coll):從當前集合中刪除兩個集合中不同的元素,使得當前集合僅保留與c集合中的元素相同的元素,即當前集合中僅保留兩個集合的交集,即this = this ∩ coll;
  • (4)void clear():清空集合
  • (5)boolean removeIf(Predicate<? super E> filter) :刪除滿足給定條件的此集合的所有元素。removeIf方法是**Java8**引入的。

3、查詢與獲取元素

  • (1)boolean isEmpty():判斷當前集合是否為空集合。
  • (2)boolean contains(Object obj):判斷當前集合中是否存在一個與obj對象equals返回true的元素。
  • (3)boolean containsAll(Collection<?> c):判斷c集合中的元素是否在當前集合中都存在。即c集合是否是當前集合的“子集”。
  • (4)int size():獲取當前集合中實際存儲的元素個數(shù)
  • (5)Object[] toArray():返回包含當前集合中所有元素的數(shù)組
  • (6)T[] toArray(T[] arr):返回包含當前集合中所有元素的數(shù)組

4、遍歷集合

  • (1)default void forEach(Consumer<? super T> action)
  • (2)foreach循環(huán)。

所有實現(xiàn)了java.lang.Iterable接口的集合都支持foreach循環(huán)。而Collection接口就繼承了Iterable接口。

5、示例代碼

package com.atguigu.collection;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;

public class TestCollection {
    @Test
    public void test1(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        System.out.println(coll);
    }

    @Test
    public void test2(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        System.out.println(coll);

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("大數(shù)據(jù)");
        other.add("嵌入式");
        other.add("鴻蒙");

        coll.addAll(other);
        System.out.println(coll);
    }

    @Test
    public void test3(){
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        coll.remove("java");
        System.out.println(coll);

        Predicate<String> p = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.contains("a");
            }
        };
        coll.removeIf(p);
        System.out.println(coll);

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        coll.removeAll(other);

        System.out.println(coll);
    }

    @Test
    public void test4() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        coll.retainAll(other);
        System.out.println(coll);
    }


    @Test
    public void test5() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        System.out.println(coll.isEmpty());
        System.out.println(coll.size());
        System.out.println(coll.contains("java"));

        Collection<String> other = new ArrayList<>();
        other.add("尚硅谷");
        other.add("JavaEE");
        other.add("world");
        other.add("hello");
        System.out.println(coll.containsAll(other));
    }

    @Test
    public void test6() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Object[] objects = coll.toArray();
        System.out.println(Arrays.toString(objects));
        
        String[] strings = new String[0];
        strings = coll.toArray(strings);
        System.out.println(Arrays.toString(strings));
    }
    
    @Test
    public void test7() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        Consumer<String> c = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        coll.forEach(c);
    }
    
    @Test
    public void test8() {
        Collection<String> coll = new ArrayList<>();
        coll.add("hello");
        coll.add("java");
        coll.add("world");
        coll.add("atguigu");
        coll.add("chai");

        for (String s : coll) {
            System.out.println(s);
        }
    }
}

11.2 Set集合

11.2.1 Set接口介紹

`Set`接口是`Collection`的子接口,set接口沒有提供額外需要實現(xiàn)類實現(xiàn)的抽象方法。但是比`Collection`接口更加嚴格了。

Set 集合不允許包含相同的元素,即元素不可重復(fù)。

Set的常用實現(xiàn)類有:`HashSet`、`TreeSet`、`LinkedHashSet`等。

package com.atguigu.list;

import org.junit.Test;

import java.util.HashSet;

public class TestSet {
    @Test
    public void test03(){
        LinkedHashSet<String> set = new LinkedHashSet<>();//按照添加順序,不可重復(fù)
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
    @Test
    public void test02(){
        TreeSet<String> set = new TreeSet<>();//有大小順序,不可重復(fù)
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
    
    @Test
    public void test01(){
        HashSet<String> set = new HashSet<>();//無序,不可重復(fù)
        set.add("hello");
        set.add("java");
        set.add("hello");
        set.add("java");
        System.out.println(set);
    }
}

11.2.2 元素相等和重復(fù)問題

  1. HashSet和LinkedHashSet元素不可重復(fù)是依賴于equals和hashCode方法
package com.atguigu.set;

public class Circle {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }

    @Override
    public String toString() {
        return "Circle{" +
                "radius=" + radius +
                '"}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass()!= o.getClass()) return false;

        Circle circle = (Circle) o;

        return Double.compare(circle.radius, radius) == 0;
    }

    @Override
    public int hashCode() {
        long temp = Double.doubleToLongBits(radius);
        return (int) (temp ^ (temp >>> 32));
    }
}
 @Test
    public void test08(){
        HashSet<Circle> set = new HashSet<>();
        set.add(new Circle(1));
        set.add(new Circle(1));
        System.out.println(set);
    }
  1. TreeSet元素不可重復(fù)是依賴于比較器的compareTo或compare方法
package com.atguigu.set;

import org.junit.Test;

import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import java.util.TreeSet;

public class TestTreeSet {
    @Test
    public void test1(){
        //String類實現(xiàn)Comparable,所以String類的對象可以方法TreeSet中,默認按照字符的編碼值排序
        TreeSet treeSet = new TreeSet();
        treeSet.add("hello");
        treeSet.add("java");
        treeSet.add("haha");
        treeSet.add("world");
        treeSet.add("heihei");
        System.out.println(treeSet);
        //[haha, heihei, hello, java, world]
    }

    @Test
    public void test2(){
        //使用String類的定制比較器,按照中文的拼音順序
        Collator collator = Collator.getInstance(Locale.CHINA);//得到一個實現(xiàn)了Comparator接口的字符串定制比較器
        TreeSet treeSet = new TreeSet(collator);
        treeSet.add("張三");
        treeSet.add("李四");
        treeSet.add("王五");
        treeSet.add("趙六");
        System.out.println(treeSet);
        //[李四, 王五, 張三, 趙六]
        //li   wang  zhang  zhao
    }

    @Test
    public void test3(){
        //使用String類的定制比較器,按照字符串的長短
        Comparator lengthComparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                return s1.length() - s2.length();
            }
        };
        TreeSet treeSet = new TreeSet(lengthComparator);
        treeSet.add("hi");
        treeSet.add("hello");
        treeSet.add("hey");
        treeSet.add("haha");
        treeSet.add("heihei");
        treeSet.add("world");//沒添加成功  因為world和hello一樣長
        treeSet.add("java");//沒添加成功   因為java和haha一樣長
        System.out.println(treeSet);
        //[hi, hey, haha, hello, heihei]

    }

    @Test
    public void test4(){
        //使用String類的定制比較器,按照字符串的長短,長度一樣,再按內(nèi)容比較大小
        Comparator lengthComparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = (String) o1;
                String s2 = (String) o2;
                int result = s1.length() - s2.length();
                if(result == 0){
                    return s1.compareTo(s2);
                }
                return result;
            }
        };
        TreeSet treeSet = new TreeSet(lengthComparator);
        treeSet.add("hi");
        treeSet.add("hello");
        treeSet.add("hey");
        treeSet.add("haha");
        treeSet.add("heihei");
        treeSet.add("world");
        treeSet.add("java");
        System.out.println(treeSet);
        //[hi, hey, haha, java, hello, world, heihei]

    }
}

11.3 List集合

11.3.1 `List<E>`接口介紹

`java.util.List`接口繼承自`Collection`接口,是單列集合的一個重要分支,習慣性地會將實現(xiàn)了`List`接口的對象稱為List集合。

List的常用實現(xiàn)類有:`ArrayList`、`Vector`、`LinkedList`、`Stack`等。

  • List集合所有的元素是以一種==線性方式==進行存儲的
  • 它是一個元素==存取有序==的集合。即元素的存入順序和取出順序有保證。
  • 它是一個==帶有索引==的集合,通過索引就可以精確的操作集合中的元素(與數(shù)組的索引是一個道理)。
  • 集合中可以有==重復(fù)==的元素

這就像銀行門口客服,給每一個來辦理業(yè)務(wù)的客戶分配序號:第一個來的是“張三”,客服給他分配的是0;第二個來的是“李四”,客服給他分配的1;以此類推,最后一個序號應(yīng)該是“總?cè)藬?shù)-1”。

1563549818689.png

注意:

List集合關(guān)心元素是否有序,而不關(guān)心是否重復(fù),請大家記住這個原則。例如“張三”可以領(lǐng)取兩個號。

在JavaSE中`List`名稱的類型有兩個,一個是`java.util.List<E>`集合接口,一個是`java.awt.List`圖形界面的組件,別導(dǎo)錯包了。

11.3.2 ` List<E>`接口中常用方法

List作為Collection集合的子接口,不但繼承了Collection接口中的全部方法,而且還增加了一些根據(jù)索引來操作集合元素的特有方法,如下:

1、添加元素

  • `void add(int index, E ele)`:把元素添加到指定位置
  • `boolean addAll(int index, Collection<? extends E> eles)`:把一組元素添加到指定位置

2、刪除元素

  • `E remove(int index)`:刪除指定位置的元素

3、修改元素

  • `E set(int index, E ele)`:替換[index]位置的元素
  • `default void replaceAll(UnaryOperator<E> operator)`:按指定操作的要求替換元素

4、獲取元素

  • `E get(int index)`:返回[index]位置的元素
  • `List subList(int fromIndex, int toIndex)`:返回[fromIndex, toIndex)范圍的元素
  • `int indexOf(Object obj)`:查詢obj在列表中的位置,如果有重復(fù),返回第1個
  • `int lastIndexOf(Object obj)`:查詢obj在列表中的地位,如果有重復(fù),返回最后1個

5、其他方法

  • `default void sort(Comparator<? super E> c) `:對List集合元素進行排序,如果想要通過元素的自然比較器排序,調(diào)用sort方法時傳入null即可。

示例代碼

package com.atguigu.list;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.UnaryOperator;

public class TestList {
    @Test
    public void test1(){
/*
        ArrayList是List接口的實現(xiàn)類。
        演示添加add
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.add(0,"atguigu");
        list.add(2,"world");

        System.out.println(list);//[atguigu, hello, world, java]


        List<String> list2 = Arrays.asList("chai", "lin", "yan");

        list.addAll(1,list2);
        System.out.println(list);//[atguigu, chai, lin, yan, hello, world, java]
    }

    @Test
    public void test2(){
 /*
        ArrayList是List接口的實現(xiàn)類。
        演示刪除remove(index)
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.remove(0);
        System.out.println(list);
    }

    @Test
    public void test3(){
       /*
        ArrayList是List接口的實現(xiàn)類。
        演示刪除
         */
        List<Integer> list =new ArrayList<>();
        list.add(10);
        list.add(20);
        list.add(30);
        list.add(40);

        list.remove(1);//刪除[1]位置的元素
        System.out.println(list);//[10, 30, 40]

        //list.remove(30);//刪除元素值為30的元素
        list.remove(Integer.valueOf(30));//手動裝箱
        System.out.println(list);//[10, 40]
    }

    @Test
    public void test4(){
         /*
        ArrayList是List接口的實現(xiàn)類。
        演示修改替換
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");

        list.set(0,"hi");
        System.out.println(list);//[hi, java]

        UnaryOperator<String> u = new UnaryOperator<String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        };
        list.replaceAll(u);
        System.out.println(list);//[HI, JAVA]
    }

    @Test
    public void test5(){
                 /*
        ArrayList是List接口的實現(xiàn)類.
        演示查詢,截取
         */
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("mysql");
        list.add("java");

        System.out.println(list.get(1));//java
        System.out.println(list.indexOf("java"));//1
        System.out.println(list.lastIndexOf("java"));//4

        List<String> subList = list.subList(1, 3);//[1,3)下標范圍的元素
        System.out.println("subList = " + subList);//[java, world]
    }

    @Test
    public void test6(){
        //演示排序
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");
        list.add("mysql");
        list.add("java");
        System.out.println(list);

        list.sort(null);
        System.out.println(list);

        Comparator<String> c = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length()-o2.length();
            }
        };
        list.sort(c);
        System.out.println(list);

    }
}