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 ts = new TreeSet(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 map = new HashMap();

        for (Iterator 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

你可能感兴趣的:(java)