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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值