Java 基于基数的自定义哈希函数

Java 基于基数的自定义哈希函数,java,hash,hashmap,Java,Hash,Hashmap,我想开发一个哈希函数,该函数接收一个位集对象,并根据位集中的数字1生成哈希值。该数字使用以下公式计算: BitSet b = new Bitset(); int card = b.cardinality(); 例如: 110 1 010 111 我想要一个按以下顺序返回元素的映射: 1 010 110 111 或 Io ho provato una soluzione Utilizando目标客户地图: map = new TObjectIntCustomHashMap<BitSet

我想开发一个哈希函数,该函数接收一个位集对象,并根据位集中的数字1生成哈希值。该数字使用以下公式计算:

BitSet b = new Bitset();
int card = b.cardinality();
例如:

110
1
010
111
我想要一个按以下顺序返回元素的映射:

1
010
110
111

Io ho provato una soluzione Utilizando目标客户地图:

map = new TObjectIntCustomHashMap<BitSet>( new HashingStrategy<BitSet>() {
            @Override
            public int computeHashCode( BitSet str ) {
                return System.identityHashCode( str );
            }

            @Override
            public boolean equals( BitSet str1, BitSet str2 ) {
                return (str1.cardinality() < str2.cardinality());
            }
        });
map=new-tobjectntcustomhashmap(new-HashingStrategy()){
@凌驾
公共整数计算哈希码(位集str){
返回系统识别码(str);
}
@凌驾
公共布尔等于(位集str1、位集str2){
返回(str1.cardinality()

但是结果并不像预期的那样。

我认为从用户93335240构建的最干净的解决方案是将自定义比较器应用于
树集
,从而允许像这样的
O(nlogn)
解决方案:

Set<Integer> t = new TreeSet<>((a, b) -> { a.cardinality() - b.cardinality() });
t.forEach((a) -> System.out.println(a));
Set t=newtreeset((a,b)->{a.cardinality()-b.cardinality()});
t、 forEach((a)->System.out.println(a));
您可以在其中创建自己的包装器,以提供
cardinality()
功能

不能使用哈希,因为它不能保证发生冲突时哈希代码值的分布。您可以尝试线性探测之类的方法,但不能保证它是正确的


事实上,如果你得到一个sub
O(nlogn)
解决方案,这将是一个很好的解决方案。

来回答你,即使我认为@MathBunny是正确的。。。与其使用hashmap当前implem的副作用,不如使用专门的结构来处理您的需求。。。这是你要找的

public class HashTest {
    public static class BitSet extends java.util.BitSet {

        private static final long serialVersionUID = 4014851086683360760L;

        public BitSet(int i) {
            super(i);
        }

        public BitSet() {
            super();
        }

        @Override
        public int hashCode() {
            return stream().map(i -> (int) Math.pow(2, i)).sum();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof java.util.BitSet) {
                return obj == null ? false : obj.hashCode() == hashCode();
            } else {
                return false;
            }
        }
    }

//  1
//  010
//  110
//  111
    public static void main(String[] args) {
        BitSet bitset1 = new BitSet(1);
        bitset1.set(0);
        BitSet bitset2 = new BitSet(3);
        bitset2.set(1);
        BitSet bitset3 = new BitSet(3);
        bitset3.set(1);
        bitset3.set(2);
        BitSet bitset4 = new BitSet(3);
        bitset4.set(0);
        bitset4.set(1);
        bitset4.set(2);
        Map<BitSet, String> map = new HashMap<>();
        map.put(bitset1, "bitset1");
        map.put(bitset2, "bitset2");
        map.put(bitset3, "bitset3");
        map.put(bitset4, "bitset4");
        map.forEach((k, v) -> System.out.println(v));

    }

}
公共类HashTest{
公共静态类位集扩展了java.util.BitSet{
私有静态最终长serialVersionUID=4014851086683360760L;
公共位集(int i){
超级(i);
}
公共位集(){
超级();
}
@凌驾
公共int hashCode(){
返回流().map(i->(int)Math.pow(2,i)).sum();
}
@凌驾
公共布尔等于(对象obj){
if(obj instanceof java.util.BitSet){
返回obj==null?false:obj.hashCode()==hashCode();
}否则{
返回false;
}
}
}
//  1
//  010
//  110
//  111
公共静态void main(字符串[]args){
BitSet bitset1=新的位集(1);
比特集1.set(0);
BitSet bitset2=新的位集(3);
比特集2.set(1);
BitSet bitset3=新的位集(3);
比特集3.set(1);
比特集3.set(2);
BitSet bitset4=新的位集(3);
比特集4.set(0);
比特集4.set(1);
比特集4.set(2);
Map Map=newhashmap();
map.put(位集1,“位集1”);
map.put(比特集2,“比特集2”);
map.put(比特集3,“比特集3”);
map.put(比特集4,“比特集4”);
map.forEach((k,v)->System.out.println(v));
}
}

好的,那么你的问题是什么?执行起来似乎不是很难,到底是什么卡住了?您是否尝试了产生意外结果的操作?您需要一个“按此顺序返回元素的映射”,因此,如果您想要一个有序映射,请使用
树集
,然后制作一个对象来封装
,然后覆盖
比较器()
function他似乎想将其集成到一个
Map
结构中,在Java中,你不能有一个自定义的
hashCode
函数,除非你喜欢组合而不是继承。HashMap不能保证它的键按哈希顺序排列。试着在HashMap中添加一些随机整数。整数hashCode是整数本身的值。在映射上迭代,您会看到它们没有被排序。HashMaps并不总是按hashcode顺序存储条目。另外,你的答案中的哈希代码不是OP所要求的(他只希望它等于基数,即只是位数集,而不是位数集的整数表示)。我完全同意你的观点。顺序只是当前哈希映射实现的副作用。如果你使用的是大数,那么这将完全失效(超过32位时)但在J8中,这项关于小数据的工作……他要求的……我完全同意你的看法,这既不安全,也不是一个好的做法!@ArnaultLePrévost Corvellec感谢你的帮助,但如果我把001和010放在一起,哈希代码会产生相同的值,元素会重叠。这是个问题。eu nop……位集bit0=新位集(3);bit0.set(0,false);bit0.set(1,true);bit0.set(2,false);BitSet bit1=new BitSet(3);bit1.set(0,true);bit1.set(1,false);bit1.set(2,false);System.out.println(bit0+“”+bit0.hashCode());System.out.println(bit1+“”+bit1.hashCode());此显示{1}2{0}1hascode将位集的值计算为无符号整数
public class HashTest {
    public static class BitSet extends java.util.BitSet {

        private static final long serialVersionUID = 4014851086683360760L;

        public BitSet(int i) {
            super(i);
        }

        public BitSet() {
            super();
        }

        @Override
        public int hashCode() {
            return stream().map(i -> (int) Math.pow(2, i)).sum();
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof java.util.BitSet) {
                return obj == null ? false : obj.hashCode() == hashCode();
            } else {
                return false;
            }
        }
    }

//  1
//  010
//  110
//  111
    public static void main(String[] args) {
        BitSet bitset1 = new BitSet(1);
        bitset1.set(0);
        BitSet bitset2 = new BitSet(3);
        bitset2.set(1);
        BitSet bitset3 = new BitSet(3);
        bitset3.set(1);
        bitset3.set(2);
        BitSet bitset4 = new BitSet(3);
        bitset4.set(0);
        bitset4.set(1);
        bitset4.set(2);
        Map<BitSet, String> map = new HashMap<>();
        map.put(bitset1, "bitset1");
        map.put(bitset2, "bitset2");
        map.put(bitset3, "bitset3");
        map.put(bitset4, "bitset4");
        map.forEach((k, v) -> System.out.println(v));

    }

}