1. 程式人生 > >Java的資料結構相關的類實現原理,比如LinkedList,ArrayList,HashMap,TreeMap

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與==具體可參考:

http://blog.csdn.net/tcytcy123/article/details/50836323
下面是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