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