1. 程式人生 > 實用技巧 >Java(23)集合

Java(23)集合

集合

Java集合類存放於Java.util包中,是一個用來存放物件的容器

  • 集合只能用來存放物件。如果存放一個int整型資料進入集合中,會自動將int轉換成Integer包裝類。
  • 集合存放的是多個物件的引用,物件本身存放在堆記憶體中。
  • 集合可以存放不同型別,不同數量的資料型別。jdk5之後,Java提供了泛型,可以限制集合中的資料型別。

陣列其實是一種特殊的集合,為什麼還要有集合呢

這是因為陣列有如下限制:

  • 陣列初始化後大小不可變;
  • 陣列只能按索引順序存取。

因此,我們需要各種不同型別的集合類來處理不同的資料,例如:

  • 可變大小的順序連結串列;
  • 保證無重複元素的集合;
  • ...

Java集合主要分為三大體系:

  1. Set:無序、不可重複的集合
  2. List:有序,可重複的集合
  3. Map:具有對映關係的集合(key-value)

Set

HashSet類

HashSetSet介面的實現類。HashSet按照Hash演算法來儲存集合中的元素,因此具有很好的儲存和查詢效能。

HashSet特點:

  • 不能保證元素的排序:存入一個物件時會呼叫該物件的hashCode()方法得到hashCode值,再根據hashCode值決定元素儲存位置。
  • 不可重複:不可重複的意思是hashCode不能相同。
  • HashSet不是執行緒安全的。
  • 集合元素可以是null

案例1:

package day01;

import java.util.HashSet;
import java.util.Set;

public class DayB {
    public static void main(String[] args) {
        Set sa= new HashSet();
        //新增元素
        sa.add("I love you");
        sa.add(34);
        System.out.println(sa); //[34, I love you]
        //判斷是否包含元素
        System.out.println(sa.contains(34)); //true
        //移除元素
        sa.remove(34);
        System.out.println(sa); //[I love you]
        //獲取集合中元素個數:
        System.out.println(sa.size());//1
        //清空元素
        sa.clear();
        System.out.println(sa); //[]
    }
}

案例2:遍歷集合

package day01;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class DayB {
    public static void main(String[] args) {
        Set sb= new HashSet();
        sb.add("a");
        sb.add("b");
        sb.add("c");
        //使用迭代器遍歷:
        Iterator it=sb.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //使用For each迴圈遍歷:
        for(Object a:sb){
            System.out.println(a);
        }
    }
}

補充知識點(迭代器)

迭代器是一種設計模式,它是一個物件,它可以遍歷並選擇序列中的物件。使用方法iterator()可要求容器(集合等)返回一個Iteratoriterator()方法是java.lang.Iterable介面,被Collection繼承。

Iterator介面主要用於遍歷Collection集合中的元素,Iterator物件稱為迭代器。

  • 使用`Iterator`的`next()`可獲得序列中的下一個元素。第一次呼叫`next()`方法時,它返回序列的第一個元素。
    
  • 使用`Iterator`的`hasNext()`可檢查序列中是否還有元素。
    
  • 使用`remove()`將迭代器新返回的元素刪除。
    

案例3:泛型---將集合設定為只能存放某型別物件

package day01;

import java.util.HashSet;
import java.util.Set;

public class DayB {
    public static void main(String[] args) {
        Set <String>sc= new HashSet<String>();
        sc.add("Hello");
        sc.add(24);  //編譯會報錯,只能存放字串型別物件
        
        Set sd=new HashSet();//相當於: Set<Object>sd=new HashSet<>();
    }
}
//後面會詳細將泛型

TreeSet類

TreeSetSortedSet介面的實現類:

  • HashSet是無序的,因為它實現了Set介面,並沒有實現SortedSet介面

  • TreeSet是有序的,因為它實現了SortedSet介面。

TreeSet支援兩種排序:自然排序(預設採用)和定製排序

  • 自然排序:TreeSet呼叫集合元素的CompareTo(Object obj)方法比較元素間大小關係,並將集合元素按升序排序。 TreeSet集合裡,建議必須放入同樣型別的物件(因為預設會進行排序),否則可能發生型別轉換異常,可以通過泛型進行限制
  • 定製排序:若定製排序,需要存放到集合中的物件對應的類實現Comparator介面,並重寫int Compare()方法。

案例1:自然排序

package day01;

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

public class DayB {
    public static void main(String[] args) {
        Set <Integer>sg= new TreeSet<Integer>();
        sg.add(234);
        sg.add(7);
        sg.add(34);
        for (Integer a:sg){
            System.out.println(a);
        }
    }
}
/*執行結果為:
7
34
234
*/

案例2:定製排序----將Person類的物件存到集合中,並按照物件的age值來進行排序。

package day01;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

public class DayB {  //執行類
    public static void main(String[] args) {
        Set<Person> sk=new TreeSet<Person>(new Person());  //這裡的泛型限制一定要加上,並且要將Person物件作為引數
        Person p1=new Person("krystal",20);
        Person p2=new Person("Jimmy",21);
        Person p3=new Person("anna",14);
        Person p4=new Person("bob",63);
        sk.add(p1);
        sk.add(p2);
        sk.add(p3);
        sk.add(p4);
        for(Person a:sk){
            System.out.println(a.getName()+" : "+a.getAge());
        }

    }
}
class Person implements Comparator<Person>{ //這裡一定要加上泛型限制,不然報錯
    private int age;
    private String name;
    public Person(){

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

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    @Override
    public int compare(Person o1, Person o2) { //注意這裡的引數要是Person類
        if(o1.getAge() > o2.getAge()){ //將>和<調換即可反向排序
            return 1;
        }else if(o1.getAge()<o2.getAge()){
            return -1;
        }else {
            return 0;
        }
    }
}
/*執行結果為:
anna : 14
krystal : 20
Jimmy : 21
bob : 63
*/

List

ArrayList類

ArrayListList介面的實現類。ArrayList是執行緒不安全的。

  • List是有序可重複的集合,集合中的元素都有對應的索引。
  • List可以通過索引來訪問集合指定位置的元素
  • List將元素新增順序設定為預設索引
  • List添加了一些通過索引操作集合的方法,如上圖

Vector(執行緒安全)也是List介面的實現類,雖然是執行緒安全的,但是比較古老了,不推薦使用。

案例1

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

public class DayB{
    public static void main(String[] args) {
        List<Integer> la=new ArrayList<Integer>();
        la.add(3);  //索引下標為0
        la.add(53); //索引下標為1
        la.add(21); //索引下標為2
        System.out.println(la);
        System.out.println(la.get(2)); //訪問索引為2的元素

        la.add(2,44); //在索引為2的位置新增元素44
        System.out.println(la);

        List lb=new ArrayList();
        lb.add(99);
        lb.add(100);
        la.addAll(2,lb); //在索引位置新增另一個List集合
        System.out.println(la);

        la.add(99);
        System.out.println(la);
        System.out.println(la.indexOf(99)); //檢視元素第一次出現的索引
        System.out.println(la.lastIndexOf(99));  //檢視元素最後一次出現的索引

        la.remove(4);//移除索引4對應的元素
        la.set(2,1024); //將索引為2的元素的值改為1024

        List subl=la.subList(1,4);
        //將1到3索引的元素作為子集subl,sublist()的作用是返回一個子集物件,左閉右開
        System.out.println(subl);
    }
}

Map

HashMap類

HashMap是Map介面的實現類,Map介面比較特別,它並沒有去繼承Collection介面。

  • Map儲存對映關係資料(key-value)
  • Map中的Key不允許重複

案例1:常用方法

package day01;

import java.util.HashMap;
import java.util.Map;

public class DayB{
    public static void main(String[] args) {
        Map mp=new HashMap();
        mp.put("krystal",20); //新增元素
        mp.put("Jimmy",21);
        System.out.println(mp);

        Map<String,Integer> mp2=new HashMap<String,Integer>(); //給Map設定泛型
        mp2.put("kobe",41);
        mp2.put("gigi",13);
        mp2.put("James",35);
        mp2.remove("James"); //根據Key移除元素
        System.out.println(mp2.size()); //返回map集合的長度
        System.out.println(mp2.containsKey("kobe"));//判斷是否包含某key
        System.out.println(mp2.containsValue("41"));  //判斷是否包含某value
        mp2.clear();//清空集合
    }
}
/*執行結果為:
{krystal=20, Jimmy=21}
2
true
false
*/

案例2:遍歷map集合

package day01;

import org.omg.PortableInterceptor.INACTIVE;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class DayB{
    public static void main(String[] args) {
        Map<String,Integer> mp2=new HashMap<String,Integer>(); //給Map設定泛型
        mp2.put("kobe",41);
        mp2.put("gigi",13);
        mp2.put("James",35);

        //方法1:建立key集合
        Set<String> keys=mp2.keySet();  //建立key集合,keySet()可以返回key集合
        for(String s:keys){
            System.out.println(s+" : "+ mp2.get(s));
        }
        //方法2:使用entrySet()方法:
        Set<Map.Entry<String, Integer>> a=mp2.entrySet();
        for(Map.Entry<String,Integer> en:a){
            System.out.println(en.getKey()+" : "+en.getValue());
        }

    }
}

HashMap與HashTable

HashMap和Hashtable是Map介面的兩個典型實現類,兩者區別:

  • Hashtable是一個古老實現類,不推薦使用
  • Hashtable執行緒安全,HashMap執行緒不安全
  • Hashtable允許使用null作為key和value,HashMap可以
  • Hashtable與HashMap都不能保證key-value的順序
  • Hashtable與HashMap判斷兩個key相同的標準都是equals()返回true,hashCode值也相等
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class DayB{
    public static void main(String[] args) {
        Map<String,Integer>ma=new HashMap<String,Integer>();
        ma.put(null,null); //執行不會報錯

        Map<String,Integer>mt=new Hashtable<String,Integer>();
        ma.put(null,null); //執行會報錯
    }
}

TreeMap類

TreeMapTreeSet一樣,是有序的。

TreeMapKey的排序:

  • 自然排序:TreeMap的所有Key必須實現Comparable介面,且所有的Key應該是同一個類的物件,否則會丟擲異常ClassCastException
  • 定製排序:MapKey不需要實現Comparable介面,但是要實現Comparator介面。

案例1:TreeMap自然排序

package day01;

import java.util.Map;
import java.util.TreeMap;

public class DayB{
    public static void main(String[] args) {
        Map<Integer,String> mL=new TreeMap<Integer, String>();
        mL.put(3,"apple");
        mL.put(2,"banana");
        mL.put(5,"grape");
        System.out.println(mL);
    }
}
/*執行結果為:
{2=banana, 3=apple, 5=grape}
*/
//所有的基本資料型別的包裝類都實現了Comparable介面,例如,Integer的原始碼如下:
public final class Integer extends Number implements Comparable<Integer>{}

案例2:TreeMap定製排序

package day01;

import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class DayB {
    public static void main(String[] args) {
        Map<Shoe,String> mS = new TreeMap<Shoe, String>(new Shoe());
        Shoe s1=new Shoe("Jimmy",21);
        Shoe s2=new Shoe("Krystal",20);
        Shoe s3=new Shoe("who",31);
        mS.put(s1,"第一個人");
        mS.put(s2,"第二個人");
        mS.put(s3,"第三個人");
        System.out.println(mS);

        Set<Shoe> a= mS.keySet();
        for(Shoe i:a){
            System.out.println(i.age);
        }
    }
}

class Shoe implements Comparator<Shoe> {
    public int age;
    public String name;

    public Shoe() {

    }

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

    @Override
    public int compare(Shoe o1, Shoe o2) {
        if (o1.age > o2.age) {
            return 1;
        } else if (o1.age < o2.age) {
            return -1;
        } else {
            return 0;
        }
    }
}

工具類Collections

注意這裡說的是Collections類,是有s的,不是Collection介面。