星期一, 10月 29, 2012

OCPJP Day 12



  • Map <<interface>> (Key-value 的配對) 沒有順序(不記住加進來的順序)
    • Hashtable(Thread-safe)
      • Properties (Key-value 都是String)
    • HashMap(Non-Thread-safe)
    • LinkedHashMap(順序)(會記住加進來的順序)
    • SortedMap <<interface>>
      • TreeMap

Notes:
  • Map 是使用Key-Value 儲存


HashMapDemo.java

package mod14;

import java.util.*;

public class HashMapDemo{
public static void main(String[] args){
Map<Integer,String> fruits = new HashMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//HashMap是不排序的如果是整數可能只是恰巧
System.out.println(fruits);
}
}


LinkedHashMap.java

package mod14;

import java.util.*;
public class LinkedHashMapDemo{
public static void main(String[] args){
Map<Integer,String> fruits = new LinkedHashMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//LinkedHaskMap 會記住放進來的順序,但是不會排序
System.out.println(fruits);
}
}
TreeMap.java

package mod14;

import java.util.*;
public class TreeMapDemo{
public static void main(String[] args){
TreeMap<Integer,String> fruits = new TreeMap<Integer,String>();
fruits.put(2,"Lemon");
fruits.put(4,"Watermelon");
fruits.put(1,"Pineapple");
fruits.put(5,"Cherry");
fruits.put(3,"Strawbarry");
//TreeMap 會排序
System.out.println(fruits);
}
}

*陣列或List的排序
  • 陣列排序用Arrays.sort();
  • List排序用Collections.sort();
  • 加入的元素一定要是Comparable (必須實作Comparable這個interface)
  • 自訂排序java.util.Comparator

public void getSorted(Set s){
//Set 要排序的方法
//方法1. 建立一個 TreeSet , 然後將Set 傳入 (因為只有TreeSet 會排序)
TreeSet ts = new TreeSet(s);
//方法2. 建立一個 ArrayList 然後將Set 傳入
ArrayList al = new ArrayList(s);
Collections.sort(al);

}


Lab:

User.java

package lab14;

// implements Comparable 來排序, 排序的方式1
public class User implements Comparable<User> {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return "<"+firstName+" "+lastName+">";
}
public int compareTo(User arg0) {
//if return value is 0, equal
return firstName.compareTo(arg0.getFirstName());
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((firstName == null) ? 0 : firstName.hashCode());
result = PRIME * result + ((lastName == null) ? 0 : lastName.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;
final User other = (User) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}

}

SortByLastName.java

package lab14;
import java.util.Comparator;
// 除了上面的實作Comparable以外,另外一種方法就是實作Comparator
public class SortByLastName implements Comparator<User> {

public int compare(User arg0, User arg1) {
return arg0.getLastName().compareTo(arg1.getLastName());
}

}


TestUser.java

package lab14;

import java.util.*;


public class TestUser {

public static void main(String[] args) {
ArrayList<User> users = new ArrayList<User>();
users.add(new User("John","Wang"));
users.add(new User("Richard","Chang"));
users.add(new User("Vivid","Su"));
users.add(new User("Mary","Chou"));
users.add(new User("Nancy","Wu"));
System.out.println(users);
//Sort by First Name
Collections.sort(users);
System.out.println(users);
//Sort by Last Name
Collections.sort(users,new SortByLastName());
System.out.println(users);
}

}

Lab: 承上例如果要以年紀來排序

建立一個依照年紀排序的 Comparator
AgeComparator.java

package lab14;

import java.util.Comparator;

public class AgeComparator implements Comparator<User> {

@Override
public int compare(User o1, User o2) {
//將兩個使用者的年齡相減來return
return o1.getAge()-o2.getAge();
}
}

User.java

package lab14;

// implements Comparable 來排序, 排序的方式1
public class User implements Comparable<User> {

private String firstName;
private String lastName;
//加入 int age 並封裝
private int age;

public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
//加入建構子
public User(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

//修改toString()
@Override
public String toString() {
return "<" + firstName + " " + lastName + this.age+ ">";
}

public int compareTo(User arg0) {
//if return value is 0, equal
return firstName.compareTo(arg0.getFirstName());
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((firstName == null) ? 0 : firstName.hashCode());
result = PRIME * result + ((lastName == null) ? 0 : lastName.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;
}
final User other = (User) obj;
if (firstName == null) {
if (other.firstName != null) {
return false;
}
} else if (!firstName.equals(other.firstName)) {
return false;
}
if (lastName == null) {
if (other.lastName != null) {
return false;
}
} else if (!lastName.equals(other.lastName)) {
return false;
}
return true;
}

/**
* @return the age
*/
public int getAge() {
return age;
}

/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
}

修改TestUser.java 加入年紀
TestUser.java

package lab14;

import java.util.*;

public class TestUser {

public static void main(String[] args) {
ArrayList<User> users = new ArrayList<User>();
users.add(new User("John", "Wang",15));
users.add(new User("Richard", "Chang",30));
users.add(new User("Vivid", "Su",20));
users.add(new User("Mary", "Chou",25));
users.add(new User("Nancy", "Wu",18));
System.out.println(users);
//Sort by First Name
Collections.sort(users);
System.out.println(users);
//Sort by Last Name
Collections.sort(users, new SortByLastName());
System.out.println(users);
//
Collections.sort(users, new AgeComparator());
System.out.println(users);
}
}

Notes:
  • 如果要套用反序age的排序, AgeComparator 方法反過來, 使用 return o2.getAge() - o1.getAge();

先講Chapter 16 巢狀類別

Notes:
  • 只要可以宣告變數就可以宣告巢狀類別
  • 巢狀類別的好處為可以直接存取外部類別的成員

Lab: 巢狀類別

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方

private class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}


*巢狀類別(Nested Class)簡介
  • 巢狀類別就是將類別定義在另一個類別中, 所以巢狀類別是外圍類別(Enclosing Class)的成員

*內部類別(Inner Class)
  • Non-static的巢狀類別又被稱為內部類別(Inner Class)
    • 建立跟使用的方式跟一般類別沒啥兩樣.
  • 因為內部類別是外圍類別(Enclosing Class)的非靜態成員, 所以
    • 必須先將外圍類別建立成物件
    • 藉由這個物件才能將內部類別建立成物件
  • 內部類別中不得宣告 static Member, 但有一個例外, 內部類別中可以宣告static final變數並給初值.

如果要將這類別開放出來

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方
//class A 改成 public
public class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}

Mod16.java

package mod16;

public class Mod16 {

public static void main(String[] args) {
//要先建立外圍物件
Outer o = new Outer();
Outer.A x = o.new A();
x.test();
}
}


*靜態巢狀類別(Static Nested Class)
  • 靜態巢狀類別又提升回Top-Level類別
  • 靜態巢狀類別不得參考外圍類別的非靜態成員


Lab:

Outer.java

package mod16;

public class Outer {

private int a = 100;
//巢狀類別可以放在可以宣告變數的地方
//
public class A {

public void test() {
//可以套用四種存取控制
//巢狀類別的好處為可以直接存取外部類別的成員
System.out.println(a);
}
}

//Inner Class
public void mA(){
//
A m = new A();
m.test();
}

public static class StaticA{
// you could call it with // Outer.StaticA.methodA();
public static void methodA(){
System.out.println("methodA()");
}
//沒有static 就要先建立物件
//you could call it with // Outer.StaticA y = new Outer.StaticA();
//y.methodB();
public void methodB(){
System.out.println("methodB()");
}
}
//
public void foo() {
int x = 200;
class B {
}
}

public void bar() {
int x = 300;
class B {
//名稱可以跟上面那個一樣 (區域的巢狀類別)
}
}
}


Mod16.java

package mod16;

public class Mod16 {

public static void main(String[] args) {
//要先建立外圍物件 才能呼叫
Outer o = new Outer();
Outer.A x = o.new A();
x.test();
//因為是靜態巢狀類別, 所以不需先建立外圍類別物件
Outer.StaticA.methodA();
//
Outer.StaticA y = new Outer.StaticA();
y.methodB();

}
}


*區域巢狀類別
  • 區域巢狀類別不得使用所在方法中的區域變數或參數, 除非使用所在方法中的final區域變數
  • 將類別定義在方法中稱為區域類別(Local Class)

*匿名類別(Anonymous Class)
  • new Class(...) 後面直接加上大括號 {….} , 並在大括號中宣告的新類別成員, 這就產生一個匿名類別(Anonymous Class)(把類別命令的工作交給java), 並為這個匿名類別建立物件.
  • 定義在方法中的匿名類別也可以說是一種區域類別, 與區域類別有相同的限制

沒有留言: