[Java] 13.5. 集合與物件

本節說明物件與集合的關係,如何讓Map不重複相同的物件? 將於此節說明。

 

image/svg+xml13.5. 集合與物件 – Collection & Objects import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee ( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee ( "K12345678" , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); HashSet employees = new HashSet (); employees.add ( e1 ); employees.add ( e2 ); Employee temp = null ; for ( Object o : employees ){ temp = ( Employee ) o ; System.out.println( temp.id ); } } } 執⾏結果 K12345678 K12345678 class Person { String id, name, gender; int age; } class Employee extends Person{ String employeeID; int salary; // 略過⼀些程式 public boolean equals ( Object o ){ if ( o instanceof Employee == false ) return false ; Employee e2 = ( Employee ) o ; if ( this .id == e2.id ) return true ; else return false ; } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee ( " K12345678 " , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee ( " K12345678 " , “Jack" , 25 , " 男⽣ " , "048679" , 50000 ); Employee e3 = new Employee ( " O111222333 " , “Mary" , 21 , " 女⽣ " , "004400" , 40000 ); System.out.println( e1 . equals ( e2 )); System.out.println( e1 . equals ( e3 )); } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee ( " K12345678 " , "Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee ( " K12345678 " , "Jack" , 25 , " 男⽣ " , "048679" , 50000 ); HashSet employees = new HashSet (); employees.add ( e1 ); employees.add ( e2 ); Employee temp = null ; for ( Object o : employees ){ temp = (Employee)o; System.out.println(temp. id ); } } } 執⾏結果 K12345678 K12345678 public boolean contains ( Object o2 ) { // 依序拿出集合中的物件,並分別放在 o1 變數中 if ( o1 . hashCode () == o2 . hashCode () && o1 . equals ( o2 )) return true ; } class Person { String id, name, gender; int age; } class Employee extends Person{ String employeeID; int salary; // 略過⼀些程式 public boolean equals ( Object o){ if (o instanceof Employee == false ) return false ; Employee e2 = (Employee) o; if ( this .id == e2.id) return true ; else return false ; } public int hashCode (){ return id.length (); } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee ( " K12345678 " , “Jack" , 20 , " 男⽣ " , "048679" , 40000 ); Employee e2 = new Employee ( " K12345678 " , "Jack" , 25 , " 男⽣ " , "048679" , 50000 ); HashSet employees = new HashSet (); employees.add ( e1 ); employees.add ( e2 ); Employee temp = null ; for ( Object o : employees ){ temp = (Employee)o; System.out.println(temp. id ); } } } 執⾏結果 K12345678 class OfficeRoom { String id ; public OfficeRoom( String id){ this .id = id; } } import java.util.*; class Main{ public static void main( String [] args){ Employee e1 = new Employee ( " K12345678 " , “Jack" , 20 , " 男⽣ " , "048679" , 40000 ); OfficeRoom r1 = new OfficeRoom ( " R001 " ); OfficeRoom r2 = new OfficeRoom ( " R002 " ); HashMap workArea = new HashMap (); workArea.put ( e1 , r1 ); workArea.put ( e1 , r2 ); OfficeRoom temp = (OfficeRoom) workArea.get ( e1 ); System.out.println( temp.id ); } } J13_5_1 Main.java 2. 刻意建立相同資料的員⼯物件。嗯~~希望 Set 夠聰明, 知道兩個相同資料的員⼯物件是不會再被加入到 Set 中的。 J13_5_2 Person.java 1. 這是⽬前使⽤的員⼯類別 (Employee) 3. 使⽤ Set 希望能夠保證相同資料的員⼯物件不會在 Set 中重複出現。 4. 使⽤ for 列舉 employees 變更中 HashSet 物件 中的員⼯物件,但怎麼相同員⼯的⾝份字號會重複 出現呢, HashSet 不是會去除重複的資料嗎? J13_5_2 Employee.java 1. 這是簡單的⼈員類別( Person )。 2. 這是員⼯類別( Employee ),其繼承⾃⼈員類別。 3. equals() ⽅法有 1 個參數,它是 Object 型別。有參數的原因 在於若 2 個員⼯物件要比較是否相等,⼀定是其中 1 個員⼯物件主 動的與另 1 個員⼯物件進⾏比較。換句話說,就是 1 個員⼯物件呼 equals() ⽅法,同時代入另 1 個員⼯物件進⾏比較。 4. 使⽤ instanceof 運算式,確定 o 參數中的物件,其型別是⼀個 Employee- 員⼯。若不為 Employee 型別,則回傳 false 以表⽰不相等。 5. 將物件轉型為員⼯型別 (Employee) 物件,這樣才可以存取員⼯物件上的屬性。 6. 比較 id 是否相等,若相等則表⽰是同⼀個員⼯,這時就 回傳 true 。同時這也是我們比較兩物件相等的規則。 id 相同時否則回傳 false ,表⽰這不是兩個相同的員⼯物件。 J13_5_2 Main.java 7. e1 e2 變數中的 2 個員⼯物件擁有相同的⾝份證字號,皆為 K12345678 8. e3 變數中的員⼯物件擁有不同的⾝份證字號, O111222333 9. true ,因為 e1 e2 變數中的 2 個員⼯物件的⾝份證字號是相同的,⽽ 其他的屬性的資料雖然不相同,但並非是 equals() 判斷相等的條件。 10. false ,因為 e1 e2 變數中的 2 個員⼯物件 的⾝份證字號是不相同的,因此回傳 false J13_5_3 Person.java 1. 相同⾝份證字號( id ),但可能因不同的時空背景⽽有不 同的資訊。例如 20 Jack 入公司, 25 歲薪⽔變更為 25000 元, Jack 還是同⼀位 Jack ,因此有相同的⾝份證字號。 2. 建立 HashSet 物件,希望透過 Set 的特性排除擁有相同⾝份證字號的員⼯物件。 3. 將有相同⾝份證字號的員⼯物件加入⾄ set 中。 4. 奇怪 ~~ 怎麼會有兩個相同的⾝份證字號 - K12345678 的員⼯物件,同時出現在 Set 中呢?不是改 寫了 equal() ⽅法了嗎?難道 HashSet 不會使⽤ equal() ⽅法判斷 2 個員⼯物件的⾝份證字號是否相等? 1. HashSet 透過 contains() ⽅法比較是否存在相同物件。 2. 其中透過 hashCode() ⽅法回傳值是否相同,來比較 2 個物件 是否相同。當然也會透過 equals() ⽅法比較 2 物件是否相同。 J13_5_4 Person.java J13_5_4 Employee.java 2. 這是員⼯類別( Employee ),其繼承⾃⼈員類別。 1. 這是簡單的⼈員類別( Person )。 3. 這是在先前即已改寫的 equals() ⽅法,當有 2 個員⼯物件的⾝份 證字號( id )相同時則會回傳 true ,表非 2 個員⼯物件是相等的。 4. 再次強調, hashCode() 是專為 Hash 分組技術所設的,⽤來作資料分 組⽤的,因此,若相要將員⼯物件放入 HashSet 物件中,同時希望享有去 除重複員⼯物件的功能,此時表需先改寫 hashCode() ⽅法,將相同的員 ⼯物件透過 hashCode() ⽅法取得的代碼,分配置同⼀區,⽽後才有機會 使⽤ equals() ⽅法比較是否有相同的⾝份證字號的員⼯物件存在。 5. 在此直接使⽤⾝份證字號( id )的字串長度,作為分組員⼯物件的 分組代碼。因此相同⾝份證字號的員⼯物件,必會有相同的代碼。 J13_5_4 Main.java 1. 建立相同⾝份證字號( id )的員⼯物件,即表⽰同⼀⼈。 2. 建立 HashSet 物件,希望透過 Set 的特性排除擁有相同⾝份證字號的員⼯物件。 3. 將有相同⾝份證字號的員⼯物件加入⾄ set 中。 4. 依序列出每個員⼯物件,很好!!相同⾝ 份證字號的員⼯物件不會在重複出現了。 J13_5_5 O ceRoom.java J13_5_5 Main.java 1. 辦公室類別( OfficeRoom ),其 id 表⽰⾨號。 2. 建立員⼯物件( Employee )表⽰ 1 位員⼯。 3. 建立 2 個辦公室物件,表⽰有 2 個辦公室 R001 R002 4. 建立 HashMap 物件,希望透過 HashMap 的特性 1 位員⼯只會出現在(對應⾄) 1 個辦公室中。 5. 將字號 K12345678 的員⼯物件對應⾄ 編號 R001 的辦公室物件。 6. 再次的將字號 K12345678 的員⼯物件 對應⾄編號 R002 的辦公室物件。 7. 透過字號 K12345678 的員⼯物件取出的辦公室物件其編號 會是 R002 ,原因是字號 K12345678 的員⼯物件早已存取,因 此會以修改的⽅式,重新對應⾄新的辦公室物件 R002 員⼯物件在 Set 中重複出現了? 1 1 1 步,改寫 equals() ⽅法,以制定員⼯物件相等的條件 改寫 equals() ⽅法後, 怎麼 HashSet 中還是出現相同的員⼯物件? 原來集合是使 equals()+hashCode() ⽅法, 判斷是否已包含相同的物件 2 步,改寫 hashCode() ⽅法, 讓相同的員⼯物件傳回相同的分組代碼 現在員⼯物件在 Set 中也能保有唯⼀性 1 1 當然,員⼯物件不重複的特性 也可以當作 Map Key 來使⽤

留言