顯示具有 java foundation 標籤的文章。 顯示所有文章
顯示具有 java foundation 標籤的文章。 顯示所有文章

2008年10月14日 星期二

static 的使用時機

首先大致了解一下 static 這個修飾字,及使用規則。

static 是屬於類別層級的修飾字,在記憶體裡面只存有一份,不論我們 new 了幾個物件,該成員或函示始終指向同一個記憶體位置。而 static 成員只能被 static 成員呼叫或存取。

在使用的時機方面,static 是在任何物件運作之前就會被呼叫的,因此我們也常常使用
main method 來作測試,再來就是常見的公用 method,類似 Utilites,與不會改變的常數等等。

下列有個例子舉的很好,可以拿來說明:

public class StaticModifier
{
int counter1 = 0;
static int counter2 = 0;

public void Increase(String s)
{
counter1++;
counter2++;
System.out.print(s + "'s counter1 = " + counter1);
System.out.println("; counter2(static) = " + counter2);
}

public static void main(String argv[])
{
StaticModifier sta1 = new StaticModifier();
StaticModifier sta2 = new StaticModifier();

sta1.Increase("sta1");
sta1.Increase("sta1");
sta2.Increase("sta2");
}
}
程式輸出為:
sta1's counter1 = 1; counter2(static) = 1
sta1's counter1 = 2; counter2(static) = 2
sta2's counter1 = 1; counter2(static) = 3
Reference:
http://www.javaworld.com.tw/jute/

2008年10月12日 星期日

Override equals(), override hashCode()

這項規則可以參考 java.lang.Object 的規格書

1. 在同一個應用程式執行期間, 對同一個物件呼叫 hashCode(), 必須回傳相同的整數結果
2. 如果兩個物件被 equals(Object) 視為相等, 則這兩個物件呼叫 hashCode() 必須獲得相同的整數結果
3. 如果兩個物件被 equals(Object) 視為不相等, 則這兩個物件呼叫 hashCode() 不必獲得相同的整數結果

若要方便產生這些原始碼,也可以參閱 commons.lang.builder
org.apache.commons.lang.builder

另外我們可以研究一下 java.lang.Object, java.lang.String 底下的原始碼
java.lang.Object

public boolean equals(Object obj) {
return (this == obj);
}
java.lang.String
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
很明顯的,equals()在比較是否 reference 到同一個記憶體位置,若為 String 物件,則比對物件的內容。

2007年9月12日 星期三

Collections API 簡介

Collections 提供了很多好用的method讓您操作資料結構
以下用一個簡單的範例來介紹:

double array[] = {123, 112, 57, 355, 255};
double subArr[] = {57};

List<Double> list = new ArrayList();
List subList = new ArrayList();

for (int i = 0; i < array.length; i++) {
list.add(new Double(array[i]));
}

for (int j = 0; j < subArr.length; j++) {
li.add(new Double(subArr[j]));
}

//排序, 印出 57,112,123,255,355
Collections.sort(list);

//反向排序
Collections.sort(list, Collections.reverseOrder());

//亂數排序
Collections.shuffle(list);

//倒轉元素, 印出 255,355,57,112,123
Collections.reverse(list);

//移動元素, 正數元素會往右移動, 負數則往左移動
Collections.rotate(list, 1);

//元素出現的頻率, 該例回傳 1
Collections.frequency(list, new Double(112));

//搜尋該元素的位置, 但使用該 method 必須是先排序過的
//例如使用Collections.sort(), 不然會回傳負值, 本例印出 1
Collections.binarySearch(list, new Double(112));

//將新元素取代原來的物件內容, 該例會全部印出 100
Collections.fill(list, new Double(100));

//比較子元素最後的位置, 本例印出 2(若找不到回傳-1)
Collections.lastIndexOfSubList(list,subList)

//比較子元素的位置
Collections.indexOfSubList(list,subList)

2007年8月10日 星期五

Collection Framework 概觀

Collection Framework 是實現資料結構的重要介面, 基本上如下表所示,
其中 Set, List 繼承於 Collection 介面.
Set --> StoredSet
Map --> StoredMap

Interface

Implementation

Historical

Set(禁止重複)

HashSet(未排序)



TreeSet
(
照字母排序)

LinkedHashSet
(按照加入的順序排序,
實現queue的先進先出)


List(可重複)


ArrayList
(
未排序)


LinkedList(特性同上)

Vector
Stack

(thread-safe)

Map(key-value)

HashMap(未排序)


TreeMap

(照字母排序)

LinkedHashMap
(
特性同上)

Hashtable
Properties

(thread-safe)


三個介面的特性已以大致在表中呈現, 其中 StoredSet, StoredMap
其實是利用 TreeSet, TreeMap 介面來實現. 下面舉一個簡例:
Comparator comparator = Collections.reverseOrder();
Set reverseSet = new TreeSet(comparator);
reverseSet.add("Bernadine");
reverseSet.add("Elizabeth");
reverseSet.add("Gene");
reverseSet.add("Clara");
System.out.println(reverseSet);
output: [Gene, Elizabeth, Clara, Bernadine]

該例呼叫 Collections.reverseOrder(), 再傳入一個 Comparator, 使得 TreeSet
具有倒序的效果, 然而 TreeSet 本身的特性是照字母排序的, 會先排序後, 再執行 Comparator
裡面的 method.

在 Linked 開頭的部分(LinkedHashSet, LinkedList, LinkedHashMap)
都實現了 queue 的資料結構, 也就是先進先出, 跟按照字母排序的 Tree..略有不同
一個簡例如下:
Set linkedHashSet = new LinkedHashSet();
linkedHashSet.add("Bernadine");
linkedHashSet.add("Elizabeth");
linkedHashSet.add("Will");
linkedHashSet.add("Gene");
linkedHashSet.add("Elizabeth");
linkedHashSet.add("Clara");
System.out.println(linkedHashSet);
output: [Bernadine, Elizabeth, Will, Gene, Clara]

那麼使用這些資料結構的時機, 若不需要排序的, 可以使用 Hash 的介面. 若有排序的需求,
可以利用 Tree, Linked..的介面, 但是速度會比較慢. 在 Thread-safe 方面, 則可以參考 Vector, Stack, Hashtable, Properties.

在最後補充遍巡(Iterator) Hash 的方式:
HashMap m = new HashMap();
m.put("foo", "foo");

Set entrySet = m.entrySet();
Iterator it = entrySet.iterator();

while(it.hasNext()){
Map.Entry me = (Map.Entry)it.next();
Object key = me.getKey();
Object value = me.getValue();
}
Reference:
Introduction to the Collections Framework