论坛首页 Java企业应用论坛

奇怪的HashSet 和变换后的TreeSet

浏览 8241 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (11)
作者 正文
   发表时间:2012-03-02  

HashSet ,作为Set集合的一个实现类,很多书中写到Set中不能存放重复的元素。事实上并非如此。看下面的一个简短的例子

import java.util.*;
class AddObject {
	int hashCode;

	public AddObject(int hashCode) {

		this.hashCode = hashCode;
	}

	public int hashCode() {
		return hashCode;
	}
}

public class TestHashSet {
	public static void main(String args[]) {
		// set在存储数据时需要遍历之前所存放的数据(hashCode与内存地址),用于与当前所要添加的元素进行对比。若得出结果相等,
		// 则不添加。比较的方法是:首先比较两个对象的hashCode,如果不相等,则直接添加;否则,再用equals()(比较地址)
		// 方法进行比较,如果结果返回为true,则不添加;否则,添加
		Set<AddObject> set = new HashSet<AddObject>();
		// 设置初始hashCode值
		AddObject ao = new AddObject(2);
		// 第一次添加
		set.add(ao);
		// 重新设置hashCode
		ao.hashCode = 3;
		// 再次添加
		set.add(ao);
		System.out.println(set.size());
		// 输出结果显然是2。但两次添加的对象显然是同一个对象,所以Set中不能存放重复的元素这一说法是不完善的

	}
}

 TreeSet:一个有序的Set(一般为升序)·,它是通过compareTo()这个函数来判断所添加的数据是否已经存在和排序

import java.util.*;

class A implements Comparable {
	public int compareTo(Object o) {
		// 返回值为0时,表示两个对象相等不可以添加;否则添加成功
		return 1;

	}

}

public class TestTreeSet {

	public static void main(String[] args) {

		TreeSet<A> ts = new TreeSet<A>();

		A a = new A();

		A b = new A();
		// 进行添加时,调用compareTo()方法进行比较。一来判断是否重复;二来,是为了排序
		ts.add(a);
		ts.add(b);

		System.out.println(ts.size());

	}

}

 

   发表时间:2012-03-03  
楼主回去看看effective java吧
0 请登录后投票
   发表时间:2012-03-03  
HashSet 内部使用HashMap来存,而HashMap 判断是否重复的条件是:

    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }


if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
0 请登录后投票
   发表时间:2012-03-04  
jht5945 写道
楼主回去看看effective java吧

这个,看《think in java》也可以了。
最好的方式是 www.google.com :  HashMap,  TreeSet.
我当年就这么学的   
0 请登录后投票
   发表时间:2012-03-04  
看下HashSet源码就行了    构造函数第一句话 new HashMap()
0 请登录后投票
   发表时间:2012-03-04  
难道lz真的不知道equals和hashCode这两个方法是什么关系?
0 请登录后投票
   发表时间:2012-03-04  
源码已看过。但我得到结论也并非不对,已实际验证过了。
0 请登录后投票
   发表时间:2012-03-05   最后修改:2012-03-05
楼主的想法挺有意思的.
但是你破坏了object常规协定,也就难怪集合类无法正常工作了
引用
在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
0 请登录后投票
   发表时间:2012-03-05  
lz肯专研的意识很好。  大家现在既然都告诉你你的方式错了,你就回头好好再看看吧。
0 请登录后投票
   发表时间:2012-03-05  
为了优化,hashset会缓存hash值,你更改了hash值后不会重新计算hash值,所以就放到了不同的桶中。在有些大的对象中,由于hash的计算比较复杂,所以hash的开销是很大的
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics