java集合排序-----原理
2012-10-21 21:08
302 查看
1.ArrayList存放的顺序按照放进去的顺序
2.HashSet不管怎么放,他会按照自己的排序给放好(这一点还是有点不明白,难道是他的hashcode写法和别人的不一样),不允许有重复数据。
3.TreeSet会升序排列。
4.HashMap以键值对的形式存放数据,可以出现null.
。。。。
当然还有很多关于集合的一些理论,童鞋们,看了那些每个集合的特点之后,你是不是又很多感觉到奇怪的地方,为什么HashSet不能出现重复的数据,为什么TreeSet能够实现升序排列?他们怎么知道怎样排序的,怎么排序的?相信如果你刚看集合,一定也会有这样的一个疑惑!
首先我们看一下众神之父Object类,他有两个方
public native int hashCode(); public boolean equals(Object obj) { return this == obj; }
理解了这两个方法我们就能理解HashSet是怎么实现将重复数据排除的。
我们测试一下HashSet,对象为String
public class SetTest { public static void main(String[] args) { Set<String> set = new HashSet<String>(); set.add("cxm"); set.add("cxm"); System.out.println(set.size()); } }
我们插入同样的字符:cxm,输出set的大小:
1
为什么呢?
因为String本身重写了
public int hashCode() { int i = hash; if(i == 0 && count > 0) { int j = offset; char ac[] = value; int k = count; for(int l = 0; l < k; l++) i = 31 * i + ac[j++]; hash = i; } return i; }
public boolean equals(Object obj) { if(this == obj) return true; if(obj instanceof String) { String s = (String)obj; int i = count; if(i == s.count) { char ac[] = value; char ac1[] = s.value; int j = offset; int k = s.offset; while(i-- != 0) if(ac[j++] != ac1[k++]) return false; return true; } } return false; }
这样本身的String就已经有了比较的规则,同理如果有个对象Customer,我们向往常一样往HashSet插入,看一下效果:
public class Customer { private String name; private int age; public Customer(String name, int age) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Set<Customer> set = new HashSet<Customer>(); Customer customer1 = new Customer("Tom", 15); Customer customer2 = new Customer("Tom", 15); set.add(customer1); set.add(customer2); System.out.println(set.size()); } }
我们创建了两个Customer对象,看上去这两个对象属性一样,但是往HashSet中添加时,并没有过滤到重复的数据。
2
那么我们怎么样让他过滤掉重复数据呢?
我们重写上面我们说的那两个方法,试试看:
@Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Customer)) return false; final Customer other = (Customer) obj; if (this.name.equals(other.getName()) && this.age == other.getAge()) return true; else return false; } @Override public int hashCode() { int result; result = (name == null ? 0 : name.hashCode()); return result; }
运行一下看一下结果:
1
所以说,eauqls()和hashCode()提供了对象与对象之间比较规则,如果想要实现HashSet中类似的方法,现在应该知道怎么做了吧!
下面我们再来讨论一下TreeSet等中的升序排列了,同样
对象只要实现Comparable<Object>,实现其中的:
public int compareTo(Object o) { Customer other = (Customer) o; // 先按name排序 if (this.name.compareTo(other.getName()) > 0) return 1; if (this.name.compareTo(other.getName()) < 0) return -1; // 在按age排序 if (this.age > other.getAge()) return 1; if (this.age < other.getAge()) return -1; return 0; }
这样两个对象就知道按照什么样的规则进行比较大小了:
public class Customer implements Comparable<Object> { private String name; private int age; public Customer(String name, int age) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Customer)) return false; final Customer other = (Customer) obj; if (this.name.equals(other.getName()) && this.age == other.getAge()) return true; else return false; } @Override public int hashCode() { int result; result = (name == null ? 0 : name.hashCode()); result = 29 * result + age; return result; } public int compareTo(Object o) { Customer other = (Customer) o; // 先按name排序 if (this.name.compareTo(other.getName()) > 0) return 1; if (this.name.compareTo(other.getName()) < 0) return -1; // 在按age排序 if (this.age > other.getAge()) return 1; if (this.age < other.getAge()) return -1; return 0; } public static void main(String[] args) { Set<Customer> set = new TreeSet<Customer>(); Customer customer1 = new Customer("Mom", 16); Customer customer2 = new Customer("Mom", 19); set.add(customer1); set.add(customer2); for(Customer Customer :set ) { System.out.println(Customer.getAge()); } // System.out.println(set.size()) } }
看一下结果:我们预期的结果是16永远在前面:
16 19
第二次执行的结果:
16 19
这样就实现了升序排列了,其实不管是比较是否相同,还是比较大小,对象中的规则都是我们设计对象的时候定的,只要我们复写以上的几个方法,就已经指定了比较的规则,就能实现上面说的那些功能了。
总结一下:
一: 如果java类复写equals方法,那么这个类也必须复写hashCode()方法,并且保证当两个对象用equals方法比较结果为true时,这两个对象的hashCode()方法的返回值相等.
二:如果java类实现了Comparable接口,那么这个类应该从新定义compareTo() equals() 和hashCode()方法,保证compareTo()和equals()方法采用相同的比较规则来比较两个对象是否相等,并且保证当两个对象用equals()方法比较的结果为true时,这两个对象的hashCode()方法的返回值相等.
HashSet和HashMap具有较好的性能,是Set和Map首选实现类,只有在需要排序的场合,才考虑使用TreeSet和TreeMap. LinkedList 和 ArrayList各有优缺点,如果经常对元素执行插入和删除操作,那么可以用LinkedList,如果经常随机访问元素,那么可以用ArrayList.
题外话:
如果两个对象equals(),那么他们的hashCode是否一定相等?
相关文章推荐
- Java基础知识强化之集合框架笔记47:Set集合之TreeSet保证元素唯一性和比较器排序的原理及代码实现(比较器排序)
- Java基础知识强化之集合框架笔记44:Set集合之TreeSet保证元素唯一性和自然排序的原理和图解
- 深入Java集合学习系列:HashMap的实现原理
- java中如何对数组和集合进行排序
- 转:深入Java集合学习系列:HashSet的实现原理
- java中集合中的泛型以及集合中的排序,集合的嵌套
- java 集合比较 排序
- Java中的Collections用来给集合排序
- Java集合的排序和HashCode方法详解
- Java并发集合的实现原理
- java中的数组与集合的排序
- java中,map集合排序实例
- Java集合中HashSet的实现原理
- java中对List对象集合进行排序
- 【排序算法】归并排序原理及Java实现
- Java io操作,poi导出excel,集合自带排序,日志报告
- (java集合原理)--01 HashMap的实现原理
- java 集合 排序
- Core Java --集合--HashMap的实现原理
- Java集合---ConcurrentHashMap原理分析