復習java基礎第三天(集合:Collection、Set、HashSet、LinkedHashSet、TreeSet)


一、Collection常用的方法

Java 集合可分為 Set、List 和 Map 三種體系:

Set:無序、不可重復的集合。

List:有序,可重復的集合。

Map:具有映射關系的集合。

Collection 接口是 List、Set 和 Queue 接口的父接口,

該接口里定義的方法既可用於操作 Set 集合,也可用於操作 List 和 Queue 集合:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;

public class TestCollections {

    public static void main(String[] args) {
        
        //1. 創建一個 Collection 接口的對象. 
        Collection collection = new ArrayList();
    
        //2. Collection 重要方法說明:         
        /**
         * 2.1 用於添加元素的:
         * add()
         * addAll()
         */
        Person p1 = new Person();
        collection.add(p1);
        collection.add(new Person());
        
        Collection collection2 = new ArrayList();
        collection2.add(new Person());
        collection2.add(new Person());

        collection.addAll(collection2);
        
        System.out.println(collection.size()); 
        
        /**
         * 2.2 用於訪問集合的方法: 
         * 獲取集合的長度: size()
         * 對集合進行遍歷的方法: iterator() 可以得到對應的 Iterator 接口對象. 
         * 
         * Iterator: 迭代器
         * ①. 獲取 Iterator 接口對象: 
         * ②. 使用 while 循環和 Iterator 對象遍歷集合中的每一個元素. 具體使用 Iterator 接口的
         *    hasNext() 和 next() 方法. 
         */
        Iterator iterator = collection.iterator();
        
        while(iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj); 
        }
        
        /**
         * 2.3 移除集合中的元素: 
         * remove(): 移除某一個指定的對象. 通過 equals() 方法來判斷要移除的那個元素在集合中是否存在.
                     以及是否能夠成功移除. 
         * removeAll()
         * clear(): 使集合中的元素置空. 
         */
//        collection.clear();
        
//        boolean result = collection.remove(p1);
//        System.out.println(result); 
//        
//        result = collection.removeAll(collection2);
//        
//        System.out.println(collection.size()); 
        
        /**
         * 2.4 用於檢測集合的方法
         * retains()
         * retainsAll()
         * isEmpty()
         */
        System.out.println(collection.contains(new Person()));//false
        System.out.println(collection.contains(p1));//true
        System.out.println(collection.containsAll(collection2));//true
        
        System.out.println(collection.isEmpty()); //false
//      collection.clear();
        System.out.println(collection.isEmpty()); //true
        
        /**
         * 2.5 其他方法
         * toArray(): 
         * **T [] toArray(T[]): 涉及到泛型, 后面再說. 
         * 
         * equals(): 比較兩個集合是否相等. 
         * hasCode(): 
         */
        Object [] objs = collection.toArray();
        System.out.println(objs.length); //4
        
        Person p2 = new Person();
        
        Collection collection3 = new HashSet();//可換ArrayList()試試
        collection3.add(p1);
        collection3.add(p2);
        
        Collection collection4 = new HashSet();
        collection4.add(p2);
        collection4.add(p1);
        
        System.out.println(collection3.equals(collection4)); 
        
        /**
         * 使用增強 for 循環的方式來對集合進行遍歷
         */
        for(Object obj: collection){
            System.out.println(obj); 
        }
    }
}
class Person(){}
練習代碼

 

二、Set、HashSet、LinkedHashSet

Set 集合不允許包含相同的元素,如果試把兩個相同的元素加入同一個 Set 集合中,則添加操作失敗

Set 判斷兩個對象是否相同不是使用 == 運算符,而是根據 equals 方法

注意:

1、當向 HashSet 集合中存入一個元素時,HashSet 會調用該對象的 hashCode() 方法來得到該對象的

     hashCode 值, 然后根據 hashCode 值決定該對象在 HashSet 中的存儲位置

2、如果兩個元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會

    把它們存儲在不同的位置,但依然可以添加成功。

3、HashSet 集合判斷兩個元素相等的標准:兩個對象通過 equals() 方法比較相等,並且兩個對象的 

    hashCode() 方法返回值也相等。即:如果兩個對象通過 equals() 方法返回 true,這兩個對象的

    hashCode 值也應該相同

重寫 hashCode() 方法的基本原則:

1、在程序運行時,同一個對象多次調用 hashCode() 方法應該返回相同的值。

2、當兩個對象的 equals() 方法比較返回 true 時,這兩個對象的 hashCode() 方法的返回值也應相等。

3、對象中用作 equals() 方法比較的 Field,都應該用來計算 hashCode 值。

另外:

1、LinkedHashSet 是 HashSet 的子類。

2、LinkedHashSet 集合根據元素的 hashCode 值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,

     這使得元素看起來是以插入順序保存的。

3、LinkedHashSet 性能插入性能略低於 HashSet,但在迭代訪問 Set 里的全部元素時有很好的性能。

4、LinkedHashSet 有序但不允許集合元素重復

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

/**
 * 1. Set 是 Collection 的子接口
 * 2. Set 中不允許存放相同的元素. 判定相同元素的標准是, 兩個對象各調用 equals() 方法, 返回 true
 * 3. HashSet
 * 3.1 基本特征:
 * ①. 不能保證元素的排列順序
 * ②. HashSet 不是線程安全的
 * ③. 集合元素可以使 null
 * ④. 對於 HashSet: 如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。
 * 
 * 4. LinkedHashSet:
 * 4.1 LinkedHashSet 是 HashSet 的子類
 * 4.2 使用鏈表維護元素的次序,這使得元素看起來是以插入順序保存的
 * 4.3 LinkedHashSet 不允許集合元素重復
 */
public class TestSet {

    public static void main(String[] args) {
        
        Set set = new LinkedHashSet();
                //new HashSet();
        
        set.add(null);
        System.out.println(set.size()); //1
        
        Person p1 = new Person();
        set.add(p1);
        set.add(p1);

        System.out.println(set.size()); //2
        
        set.add(new Person("AA", 12));
        set.add(new Person("AA", 12));

        System.out.println(set.size()); //3
        
        set.add(new Person("FF", 13));
        
        Iterator it = set.iterator();
        while(it.hasNext()){
            System.out.println(it.next()); 
        }
    }
}

 class Person {

//    @Override
//    public boolean equals(Object obj) {
//        return false;
//    }
    
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public Person() {
        // TODO Auto-generated constructor stub
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
//    private static int init = 0;
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
        
//    return init++;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }    
}
練習代碼

 

三、TreeSet:

TreeSet 是 SortedSet 接口的實現類,TreeSet 可以確保集合元素處於排序狀態

TreeSet 支持兩種排序方法:自然排序和定制排序默認情況下,TreeSet 采用自然排序

排序:

1、TreeSet 會調用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關系,

     然后將集合元素按升序排列。

2、如果試圖把一個對象添加到 TreeSet 時,則該對象的類必須實現 Comparable 接口

3、實現 Comparable 的類必須實現 compareTo(Object obj) 方法,兩個對象即通過

    compareTo(Object obj)方法的返回值來比較大小

Comparable 的典型實現:

BigDecimal、BigInteger 以及所有的數值型對應的包裝類:按它們對應的數值大小進行比較。

     Character:   按字符的 UNICODE 值來進行比較。

     Boolean:     true 對應的包裝類實例大於 false 對應的包裝類實例。

      String:       按字符串中字符的 UNICODE 值進行比較。

  Date、Time:   后邊的時間、日期比前面的時間、日期大。

注意:

因為只有相同類的兩個實例才會比較大小,所以向 TreeSet 中添加的應該是同一個類的對象

需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與

compareTo(Object obj) 方法有一致的結果:即如果兩個對象通過 equals() 方法比較返回 true,

則通過 compareTo(Object obj) 方法比較應返回 0.

import java.util.*;

/*
Set:無序,不可以重復元素。
    |--HashSet:數據結構是哈希表。線程是非同步的。
                保證元素唯一性的原理:判斷元素的hashCode值是否相同。
                如果相同,還會繼續判斷元素的equals方法,是否為true。

    |--TreeSet:可以對Set集合中的元素進行排序。
                底層數據結構是二叉樹。
                保證元素唯一性的依據:
                compareTo方法return 0.

                TreeSet排序的第一種方式:讓元素自身具備比較性。
                元素需要實現Comparable接口,覆蓋compareTo方法。
                也種方式也成為元素的自然順序,或者叫做默認順序。

                TreeSet的第二種排序方式。
                當元素自身不具備比較性時,或者具備的比較性不是所需要的。
                這時就需要讓集合自身具備比較性。
                在集合初始化時,就有了比較方式。

需求:
往TreeSet集合中存儲自定義對象學生。
想按照學生的年齡進行排序。

記住,排序時,當主要條件相同時,一定判斷一下次要條件。
*/

class TreeSetDemo 
{
    public static void main(String[] args) 
    {
        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi08",19));
        //ts.add(new Student("lisi007",20));
        //ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}

class Student implements Comparable//該接口強制讓學生具備比較性。
{
    private String name;
    private int age;

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

    public int compareTo(Object obj)
    {

        //return 0;        
        if(!(obj instanceof Student))
            throw new RuntimeException("不是學生對象");
        Student s = (Student)obj;

        System.out.println(this.name+"....compareto....."+s.name);
        if(this.age>s.age)
            return 1;
        if(this.age==s.age)
        {
            return this.name.compareTo(s.name);
        }
        return -1;
    }

    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
}
練習代碼(自然排序)
import java.util.*;

/*
當元素自身不具備比較性,或者具備的比較性不是所需要的。
這時需要讓容器自身具備比較性。
定義了比較器,將比較器對象作為參數傳遞給TreeSet集合的構造函數。

當兩種排序都存在時,以比較器為主。

定義一個類,實現Comparator接口,覆蓋compare方法。
*/
class Student implements Comparable//該接口強制讓學生具備比較性。
{
    private String name;
    private int age;

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

    public int compareTo(Object obj)
    {

        //return 0;
        
        if(!(obj instanceof Student))
            throw new RuntimeException("不是學生對象");
        Student s = (Student)obj;

        //System.out.println(this.name+"....compareto....."+s.name);
        if(this.age>s.age)
            return 1;
        if(this.age==s.age)
        {
            return this.name.compareTo(s.name);
        }
        return -1;
    }

    public String getName()
    {
        return name;

    }
    public int getAge()
    {
        return age;
    }
}
class TreeSetDemo2 
{
    public static void main(String[] args) 
    {
        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi02",21));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi06",18));
        ts.add(new Student("lisi06",18));
        ts.add(new Student("lisi007",29));
        //ts.add(new Student("lisi007",20));
        //ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}

class MyCompare implements Comparator
{
    public int compare(Object o1,Object o2)
    {
        Student s1 = (Student)o1;
        Student s2 = (Student)o2;

        int num = s1.getName().compareTo(s2.getName());
        if(num==0)
        {

            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
            /*
            if(s1.getAge()>s2.getAge())
                return 1;
            if(s1.getAge()==s2.getAge())
                return 0;
            return -1;
            */
        }
                
        return num;
    }
}
練習代碼(定制排序)

 

比較推薦的定制排序做法

1、首先,定義一個Person類

public class Person {
     private String name;
     private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person(){}
}
Person類

(附加的練習:Student類)

public class Student implements Comparable{
    
    private String name;
    private int age;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    
    @Override
    public int compareTo(Object o) {
        int result;
        if(o instanceof Student){
            Student stu = (Student)o;
            result = this.age-stu.age;
            if(result==0){
            return this.getName().compareTo(stu.getName());
            }
        }else{
            throw new ClassCastException("不是一個學生對象!");
        }
        return result;
    }
    
    public Student(){}
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }        
}
Student類

2、然后寫主程序類

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

public class TestTreeSet {
      public static void main(String []args){
/*          Set set = new TreeSet();
//          set.add("123");
//          set.add(123);
//          set.add(null);
//          set.add(new Student());
          set.add(new Student("lisi07",22));
          set.add(new Student("lisi02",16));
          set.add(new Student("lisi008",22));
          set.add(new Student("lisi10",19));
          
          Iterator iterator = set.iterator();
          while(iterator.hasNext()){
              Student stu = (Student) iterator.next();
              System.out.println(stu.getName()+"...."+stu.getAge());
          }
          
          for(Object obj:set){
              System.out.println(obj);
          }*/
          
          Comparator comparator = new  Comparator() {

            @Override
            public int compare(Object o1, Object o2) {
                int result;
                  if(o1 instanceof Person&& o2 instanceof Person){
                      Person p1 = (Person) o1;
                      Person p2 = (Person) o2;
                      result = p1.getAge() - p2.getAge();
                    if(result == 0){
                        return p1.getName().compareTo(p2.getName());
                      }
                  }else{
                      throw new ClassCastException("不能轉換為Person");
                 }   
                  return result;
            }
        };
        
        Set set2 = new TreeSet(comparator);
        set2.add(new Person("lisi006",12));
        set2.add(new Person("lisi002",6));
        set2.add(new Person("lisi015",20));
        set2.add(new Person("lisi013",20));
        
        Iterator iterator = set2.iterator();
        while(iterator.hasNext()){
            Person p = (Person) iterator.next();
            System.out.println(p.getName()+" "+p.getAge()+"\t");         
        }    
    }
}
主程序

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM