Java 在这种情况下可以实现hashCode()方法吗?

Java 在这种情况下可以实现hashCode()方法吗?,java,collections,equals,hashcode,Java,Collections,Equals,Hashcode,我有一个类,它有两个字符串字段。其中任何一个(但不是两个)都可以为null public class SimpleBluetoothDevice { final String macAddress; final String name; public SimpleBluetoothDevice(String name, String macAddress) { this.macAddress = macAddress; this.nam

我有一个类,它有两个字符串字段。其中任何一个(但不是两个)都可以为null

public class SimpleBluetoothDevice {

    final String macAddress;
    final String name;

    public SimpleBluetoothDevice(String name, String macAddress) {
        this.macAddress = macAddress;
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof SimpleBluetoothDevice)) {
            return false;
        }
        SimpleBluetoothDevice otherDevice = (SimpleBluetoothDevice) o;
        if (name == null || otherDevice.name == null) { 
            return otherDevice.macAddress.equalsIgnoreCase(macAddress);
        }
        if (macAddress == null || otherDevice.macAddress == null) { 
            return otherDevice.name.equals(name);
        }
        return name.equals(otherDevice.name) || macAddress.equalsIgnoreCase(otherDevice.macAddress);
    }

    @Override
    public int hashCode() {
        int hash = 1;
        hash = 31 * hash + ((name == null) ? 0 : name.hashCode());
        hash = 31 * hash + ((macAddress == null) ? 0 : macAddress.toLowerCase(Locale.US).hashCode());
        return hash;
    } }
测试

public class Main {

    private static final List<SimpleBluetoothDevice> DEVICE_LIST = new ArrayList<SimpleBluetoothDevice>();
    private static final Set<SimpleBluetoothDevice> DEVICE_SET = new HashSet<SimpleBluetoothDevice>();

    static {
        DEVICE_LIST.add(new SimpleBluetoothDevice(null, "11-22-33-44-55-aa"));
        DEVICE_LIST.add(new SimpleBluetoothDevice("iPad", "11-22-33-44-55-BB"));

        DEVICE_SET.add(new SimpleBluetoothDevice(null, "11-22-33-44-55-aa"));
        DEVICE_SET.add(new SimpleBluetoothDevice("iPad", "11-22-33-44-55-BB"));
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        SimpleBluetoothDevice bluetoothDevice = new SimpleBluetoothDevice("Android", "11-22-33-44-55-AA");
        System.out.println(DEVICE_LIST.contains(bluetoothDevice)); // TRUE
        System.out.println(DEVICE_SET.contains(bluetoothDevice)); // FALSE
    }

}
我修改了密码。因此,如果

  • 他们的名字是平等的
  • 他们的MAC地址是相等的,不考虑具体情况
  • 这两个条件都满足
更新#2.

public class Main {

    private static final List<SimpleBluetoothDevice> BLUETOOTH_DEVICES = new ArrayList<SimpleBluetoothDevice>();

    static {
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice(null, "38:ec:e4:d7:ad:a2"));
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice("Nokia N9", "40:98:4E:48:1D:B0"));
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice("Galaxy S4", "08:FC:88:AD:4A:62"));
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        SimpleBluetoothDevice one = new SimpleBluetoothDevice(null, "38:ec:e4:d7:ad:a2");
        SimpleBluetoothDevice two = new SimpleBluetoothDevice("GT-I9003", "38:ec:e4:d7:ad:a2");
        SimpleBluetoothDevice three = new SimpleBluetoothDevice("GT-I9003", "123");
        System.out.println(one.equals(two));
        System.out.println(two.equals(three));
        System.out.println("Transitivity test. " + one.equals(three));
        System.out.println("Contains test. " + BLUETOOTH_DEVICES.contains(one));
        System.out.println("Contains test. " + BLUETOOTH_DEVICES.contains(two));
        System.out.println("Contains test. " + BLUETOOTH_DEVICES.contains(three));
    }

    /**
     * This class only contains two text fields: MAC address and name.
     * 
     * @author Maxim Dmitriev
     * 
     */
    private static final class SimpleBluetoothDevice {

        final String macAddress;
        final String name;

        SimpleBluetoothDevice(String name, String macAddress) {
            this.macAddress = macAddress;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Name: " + name + ", MAC address: " + macAddress;
        }

        @Override
        public boolean equals(Object o) {
            if (o == this) {
                return true;
            }
            if (!(o instanceof SimpleBluetoothDevice)) {
                return false;
            }
            SimpleBluetoothDevice otherDevice = (SimpleBluetoothDevice) o;
            if (name == null) {
                return macAddress.equalsIgnoreCase(otherDevice.macAddress);
            } else if (macAddress == null) {
                return name.equals(otherDevice.name);
            } else {
                return name.equals(otherDevice.name) || macAddress.equalsIgnoreCase(otherDevice.macAddress);
            }
        }

        /**
         * It is recommended to override {@link Object#hashCode()} in every class that overrides
         * {@link Object#equals(Object)}. <br><br> But two instances of this class will be equal, if
         * their MAC addresses (the
         * case of the characters is ignored) or names are equal. Collections, such as
         * {@link HashSet}, {@link HashMap}, cannot be used because the hash codes of logically
         * equal instances are not the same.
         * 
         */
        @Override
        public int hashCode() {
            return 1;
        }
    }
}
没有
等于

public class Main {

    private static final Set<SimpleBluetoothDevice> BLUETOOTH_DEVICES = new HashSet<SimpleBluetoothDevice>();

    static {
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice("G1", "38:ec:e4:d7:ad:a2"));
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice("Nokia N9", "40:98:4E:48:1D:B0"));
        BLUETOOTH_DEVICES.add(new SimpleBluetoothDevice("Galaxy S4", "08:FC:88:AD:4A:62"));
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        SimpleBluetoothDevice myDevice = new SimpleBluetoothDevice(null, "38:ec:e4:d7:ad:a2");
        for (SimpleBluetoothDevice device : BLUETOOTH_DEVICES) {
            if (myDevice.macAddress == null || device.macAddress == null) {
                if (myDevice.name.equals(device.name)) {
                    System.out.println("Name");
                    break;
                }
            } else if (myDevice.name == null || device.name == null) {
                if (myDevice.macAddress.equalsIgnoreCase(device.macAddress)) {
                    System.out.println("MAC");
                    break;
                }
            } else {
                if (myDevice.macAddress.equalsIgnoreCase(device.macAddress) || myDevice.name.equals(device.name)) {
                    System.out.println("Either of them");
                    break;
                }
            }
        }
    }

    /**
     * This class only contains two text fields: MAC address and name.
     * 
     * @author Maxim Dmitriev
     * 
     */
    private static final class SimpleBluetoothDevice {

        final String macAddress;
        final String name;

        /**
         * 
         * @param name
         * @param macAddress
         * 
         * Throws an {@link IllegalArgumentException} if both parameters are null
         */
        SimpleBluetoothDevice(String name, String macAddress) {
            if (name == null && macAddress == null) {
                throw new IllegalArgumentException("Both a name and a MAC address cannot be null");
            }
            this.name = name;
            this.macAddress = macAddress;
        }
    }
}
公共类主{
专用静态最终设置BLUETOOTH_DEVICES=新HashSet();
静止的{
添加(新的SimpleBluetooth设备(“G1”、“38:ec:e4:d7:ad:a2”);
添加(新的SimpleBluetooth设备(“诺基亚N9”、“40:98:4E:48:1D:B0”);
蓝牙设备。添加(新的SimpleBluetooth设备(“Galaxy S4”,“08:FC:88:AD:4A:62”);
}
/**
*@param args
*/
公共静态void main(字符串[]args){
SimpleBluetoothDevice myDevice=新的SimpleBluetoothDevice(null,“38:ec:e4:d7:ad:a2”);
用于(SimpleBluetooth设备:蓝牙设备){
if(myDevice.macAddress==null | | device.macAddress==null){
if(myDevice.name.equals(device.name)){
System.out.println(“名称”);
打破
}
}else if(myDevice.name==null | | device.name==null){
if(myDevice.macAddress.equalsIgnoreCase(device.macAddress)){
系统输出打印项次(“MAC”);
打破
}
}否则{
if(myDevice.macAddress.equalsIgnoreCase(device.macAddress)| | myDevice.name.equals(device.name)){
System.out.println(“其中任何一个”);
打破
}
}
}
}
/**
*此类仅包含两个文本字段:MAC地址和名称。
* 
*@作者马克西姆·德米特里耶夫
* 
*/
私有静态最终类SimpleBluetoothDevice{
最终字符串地址;
最后的字符串名;
/**
* 
*@param name
*@param macAddress
* 
*如果两个参数都为null,则抛出{@link IllegalArgumentException}
*/
SimpleBluetoothDevice(字符串名称、字符串地址){
if(name==null&&macAddress==null){
抛出新的IllegalArgumentException(“名称和MAC地址都不能为空”);
}
this.name=名称;
this.macAddress=macAddress;
}
}
}
目前,您甚至无法以符合WHITH STATES声明的方式实现
equals

equals方法在非null对象引用上实现等价关系:

  • 它是可传递的:对于任何非空引用值x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true
考虑以下三个对象:

x: Name=foo MacAddress=m1
y: Name=bar MacAddress=m1
z: Name=bar MacAddress=m2
现在
x.equals(y)
将为真,
y.equals(z)
将为真,这意味着
x.equals(z)
将为真。。。但事实并非如此

在你找到一种满足传递性契约的等式之前,没有必要担心
hashCode
。如果没有其他内容,那么总是返回0的
hashCode
实现总是“正确的”(尽管在性能方面显然没有用处)。但是,当您的相等性检查被破坏时,这对您没有多大帮助。

目前,您甚至无法以符合which states的方式实现
相等:

equals方法在非null对象引用上实现等价关系:

  • 它是可传递的:对于任何非空引用值x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true
考虑以下三个对象:

x: Name=foo MacAddress=m1
y: Name=bar MacAddress=m1
z: Name=bar MacAddress=m2
现在
x.equals(y)
将为真,
y.equals(z)
将为真,这意味着
x.equals(z)
将为真。。。但事实并非如此

在你找到一种满足传递性契约的等式之前,没有必要担心
hashCode
。如果没有其他内容,那么总是返回0的
hashCode
实现总是“正确的”(尽管在性能方面显然没有用处)。但是,当您的相等性检查被破坏时,这对您没有多大帮助。

目前,您甚至无法以符合which states的方式实现
相等:

equals方法在非null对象引用上实现等价关系:

  • 它是可传递的:对于任何非空引用值x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true
考虑以下三个对象:

x: Name=foo MacAddress=m1
y: Name=bar MacAddress=m1
z: Name=bar MacAddress=m2
现在
x.equals(y)
将为真,
y.equals(z)
将为真,这意味着
x.equals(z)
将为真。。。但事实并非如此

在你找到一种满足传递性契约的等式之前,没有必要担心
hashCode
。如果没有其他内容,那么总是返回0的
hashCode
实现总是“正确的”(尽管在性能方面显然没有用处)。但是,当您的相等性检查被破坏时,这对您没有多大帮助。

目前,您甚至无法以符合which states的方式实现
相等:

equals方法在非null对象引用上实现等价关系:

  • 它是可传递的:对于任何非空引用值x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true
考虑以下三个对象:

x: Name=foo MacAddress=m1
y: Name=bar MacAddress=m1
z: Name=bar MacAddress=m2
现在
x等于(y)