Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中排序对象,不带';适当的';比较法_Java - Fatal编程技术网

在Java中排序对象,不带';适当的';比较法

在Java中排序对象,不带';适当的';比较法,java,Java,我们需要一个compareTo方法,该方法可以处理不同类的对象,并保证如果对象不相同,它永远不会返回0 Integer.compare(System.identityHashCode(o1), System.identityHashCode(o2)) 在Java中不起作用并不保证两个不同的对象将返回不同的identityHashCode(是的,是的) 一些想法?由于不同的对象可以同时具有相同的System.identityHashCode()和hashCode(),因此不确定该怎么做。可以使

我们需要一个compareTo方法,该方法可以处理不同类的对象,并保证如果对象不相同,它永远不会返回0

 Integer.compare(System.identityHashCode(o1), System.identityHashCode(o2))
在Java中不起作用并不保证两个不同的对象将返回不同的identityHashCode(是的,是的)


一些想法?

由于不同的对象可以同时具有相同的System.identityHashCode()和hashCode(),因此不确定该怎么做。可以使用“不安全”随意创建两个对象,如果创建的对象足够多,则可以随机创建两个对象

public class UnsafeIdentityDemo {

    static final Unsafe UNSAFE;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }

    public static void setIdentityHashCode(Object o, int code) {
        UNSAFE.putInt(o, 1l, code & 0x7FFF_FFF);
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Double d = 1.0;
        Double d2 = 1.0;
        setIdentityHashCode(d, 1);
        setIdentityHashCode(d2, 1);
        System.out.println("d: "+d+" System.identityHashCode(d): "+System.identityHashCode(d));
        System.out.println("d2: "+d2+" System.identityHashCode(d2): "+System.identityHashCode(d2));
        System.out.println("d == d2: " + (d == d2));
    }
}
印刷品

d: 1.0 System.identityHashCode(d): 1
d2: 1.0 System.identityHashCode(d2): 1
d == d2: false
您可以做的是根据对象被发现的顺序分配对象(IntelliJ的调试器会这样做)

公共类UniversalComparator实现Comparator{
@凌驾
公共整数比较(对象o1、对象o2){
如果(o1==o2)
返回0;
int cmp=compare(o1.getClass(),o2.getClass());
//如果类别相同,且具有可比性。
if(cmp==0&&o1可比实例)
cmp=((可比)o1)。与(o2)相比;
//否则,请使用内置的toString/hashCode/identityHashCode
如果(cmp==0)
cmp=Integer.compare(o1.toString(),o2.toString());
如果(cmp==0)
cmp=Integer.compare(o1.hashCode(),o2.hashCode());
如果(cmp==0)
cmp=整数。比较(System.identityHashCode(o1)、System.identityHashCode(o2));
//否则,为它们生成唯一的id
如果(cmp==0)
cmp=整数。比较(uniqueId(o1),uniqueId(o2));
返回cmp;
}
最终映射uniqueId=新标识hashmap();
专用同步整数唯一ID(对象o){
返回uniqueId.computeIfAbsent(o,k->uniqueId.size());
}
}
这将确保所有不同类型的对象

  • 首先按类名排序
  • 如果同一类且
    可比
    则使用内置的比较
  • 否则,如果是同一类,则通过比较
    toString()
    ,然后比较
    hashCode()
    ,然后比较
    System.identityHashCode
  • 否则,生成一个唯一的id
这意味着对于大多数对象,您将获得可预测的排序顺序


注意:这将慢慢建立所有冲突对象的映射。它将很小,但可能是内存泄漏的一个来源。一个
WeakIdentityHashMap
会更好。

这里的
不一样到底意味着什么?你不能用
==
检查引用吗?如果类完全不同,你如何知道一个对象比另一个对象大?不同类的对象?请解释一下:这是否意味着
o1
o2
在对
compareTo
的同一调用中可能属于不同的类?您需要使用compareTo对它们进行排序,还是说它们是否相同/不同?您不能为随机对象提供对称规则。@Thomas System.identityHashCode(o1)是随机生成的,因此在64K对象的集合中,它们发生冲突的可能性很高。在获取唯一id之前,还可以使用类的哈希代码来降低冲突的概率。这将进一步降低内存泄漏的风险。只是澄清一下:我不是指
o1.hashCode()
(这可能也有帮助)而是
o1.getClass().hashCode()
,因为对象可能是OP声明的不同类。@Thomas你可以,尽管我会比较类名。嗯,这有什么好处?更好定义的散列码?@Thomas您的建议让我了解了如何使大多数对象的排序顺序可预测。
public class UniversalComparator implements Comparator<Object> {
    @Override
    public int compare(Object o1, Object o2) {
        if (o1 == o2)
            return 0;
        int cmp = compare(o1.getClass(), o2.getClass());
        // if the classes are the same, and they are Comparable.
        if (cmp == 0 && o1 instanceof Comparable)
            cmp = ((Comparable) o1).compareTo(o2);
        // otherwise use the built in toString/hashCode/identityHashCode
        if (cmp == 0)
            cmp = Integer.compare(o1.toString(), o2.toString());
        if (cmp == 0)
            cmp = Integer.compare(o1.hashCode(), o2.hashCode());
        if (cmp == 0)
            cmp = Integer.compare(System.identityHashCode(o1), System.identityHashCode(o2));
        // otherwise generate a unique id for them
        if (cmp == 0)
            cmp = Integer.compare(uniqueId(o1), uniqueId(o2));
        return cmp;
    }

    final Map<Object, Integer>  uniqueId = new IdentityHashMap<>();
    private synchronized int uniqueId(Object o) {
        return uniqueId.computeIfAbsent(o, k -> uniqueId.size());
    }
}