Java的資料結構相關的類實現原理,比如LinkedList,ArrayList,HashMap,TreeMap
HashMap是不是有序的?
不是
hashmap的hashcode()生成規則是:
需要了解equals()和hashcode();
首先了解,equals和==的區別:
1、基本資料型別比較
==和Equals都比較兩個值是否相等。相等為true 否則為false;
2、引用物件比較
==和Equals都是比較棧記憶體中的地址是否相等 。相等為true 否則為false;
3、equals()提供給
需注意幾點:
1、string是一個特殊的引用型別。對於兩個字串的比較,不管是 == 和 Equals 這兩者比較的都是字串是否相同;
2、當你建立兩個string物件時,記憶體中的地址是不相同的,你可以賦相同的值。
所以字串的內容相同。引用地址不一定相同,(相同內容的物件地址不一定相同),但反過來卻是肯定的;
3、基本資料型別比較(string 除外) == 和 Equals 兩者都是比較值;
equals()通常需要物件自己定義重寫。
equals與==具體可參考:
下面是equals()在Object的實現
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
這是equals()在HashMap的實現
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
有兩種情況會判斷為相等,一是呼叫的同一個物件,二是key
第一:在某個執行時期間,只要物件的(欄位的)變化不會影響equals方法的決策結果,那麼,在這個期間,無論呼叫多少次hashCode,都必須返回同一個雜湊碼。
第二:通過equals呼叫返回true 的2個物件的hashCode一定一樣。
第三:通過equasl返回false 的2個物件的雜湊碼不需要不同,也就是他們的hashCode方法的返回值允許出現相同的情況。
總結一句話:等價的(呼叫equals返回true)物件必須產生相同的雜湊碼。不等價的物件,不要求產生的雜湊碼不相同。
那哪些map是有序的?
TreeMap和LinkedHashMap。
TreeMap和LinkedHashMap是如何保證它的順序的?
hashMap儲存結構包含key,value,next
linkedHashMap是通過儲存結構增加before和after實現順序排列的
參考:http://www.cnblogs.com/whgk/p/6169622.html
LinkedHashMap通過實現Comparator介面,重寫compare()方法來比較,比如:
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<Person>(new PersonComparator());
ts.add(new Person(1, "Json", 20));
ts.add(new Person(2, "Peter", 22));
ts.add(new Person(1, "Divid", 25));
ts.add(new Person(3, "Aglia", 27));
ts.add(new Person(3, "Alex", 23));
ts.add(new Person(3, "Molic", 22));
Map<String, Person> map = new HashMap<String, Person>();
for (Iterator<Person> iterator = ts.iterator(); iterator.hasNext();) {
Person p = (Person) iterator.next();
map.put(p.getName(), p);
System.out.println(p.getName() + "|" + p.getLevel() + "|"
+ p.getAge());
}
}
}
class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
if (p1.getLevel() == p2.getLevel()) {
return p1.getAge() - p2.getAge();
}
return p1.getLevel() - p2.getLevel();
}
總結:
首先2個都是map,所以用key取值肯定是沒區別的,區別在於用Iterator遍歷的時候
LinkedHashMap儲存了記錄的插入順序,先插入的先遍歷到
TreeMap預設是按升序排,也可以指定排序的比較器。遍歷的時候按升序遍歷。
例如:a是LinkedHashMap,b是TreeMap。
a.put(“2”,”ab”);
a.put(“1”,”bc”);
b.put(“2”,”ab”);
b.put(“1”,”bc”);
那麼遍歷a的時候,先遍歷到key是2的,因為2先放進去。
遍歷b的時候,先遍歷到“1”,因為按順序是先1後2