object的equals和hashcode方法
默认的equals和hashcode实现是怎样的(object中定义的)?
默认的equals方法时比较两个对象引用是否指向同一个地址,也就是两个对象的内存地址是不是一样的
默认hashcode方法是根据对象地址去生成一个整数的数值
只重写equals方法真的会出错吗?
这里是实体类user实现了implements Comparable<User>
只重写了euqals方法出现的问题
@Override public boolean equals(Object obj) { if (obj instanceof User) { User user = (User) obj; return this.name.equals(user.name) && this.age == user.age; } return false; }
/**
* <h2>实现/不实现 equals 方法和 hashcode 对于判等的影响</h2>
* */
private static void equalsAndHashcode() {
User user1 = new User("qinyi", 19);
User user2 = new User("qinyi", 19);
// System.out.println(user1.equals(user2));
Set<User> userSet = new HashSet<>();
userSet.add(user1);
userSet.add(user2);
Map<User, Integer> userIntegerMap = new HashMap<>();
userIntegerMap.put(user1, 0);
userIntegerMap.put(user2, 0);
System.out.println(userSet.size());
System.out.println(userIntegerMap.size());
}
输出 2 2 这明显不符合预期
所以只重写了equals方法是不行的
需要重写hashcode方法(简单)
@Override public int hashCode() { int result = name.hashCode(); result = 31 * result + age; return result; }
集合中元素的索引竟然与equals方法相关
类实现了compareTo方法(返回0表示相等,返回正数表示大于,返回负数表示小于),就需要实现equals方法
@Override public int compareTo(User o) { return (this.age - o.age) + this.name.compareTo(o.name); }
@Override public boolean equals(Object obj) { if (obj instanceof User) { User user = (User) obj; return this.name.equals(user.name) && this.age == user.age; } return false; }
/** * <h2>集合元素索引与 equals 方法相关</h2> * */ private static void compareToAndEquals() { List<User> users = new ArrayList<>(); users.add(new User("qinyi", 10)); users.add(new User("qinyi", 20)); User user = new User("qinyi", 20); int index1 = users.indexOf(user); int index2 = Collections.binarySearch(users, user); System.out.println(index1); System.out.println(index2); }
//0 1 不符合预期,应该是一样的
因为indexof方法是依据equals方法来比较的
而collections.binarySearch()方法是compareTo方法来的。
compareTo与equals的实现过程需要同步 大坑!!!
使用lombok注解没有达到预期该怎么办?
/** * <h1>lombok 第一个坑</h1> * */ private static void singleAlphabetHump() throws Exception { ObjectMapper mapper = new ObjectMapper(); Personal personal = new Personal(); personal.setIPhone("8.1"); // {"name":null,"userName":null,"iphone":"8.1"} // System.out.println(mapper.writeValueAsString(personal)); String json = "{\"name\": \"qinyi\"," + "\"userName\": \"qinyi-imooc\",\"iphone\":\"8.1\"}"; Personal personal1 = mapper.readValue(json, Personal.class); System.out.println(personal1); }
-------------------------------------------------------------------------------------------
@Data public class Personal { private String iPhone; private String name; private String userName; }
这里的坑就是用json传值的时候,如果根据实体类属性去传值,iPhone那个地方会报错,这是因为对于单字母的驼峰形式传值,lombook会将其全部转化为小写的形式,所以,我们在单字母命名的时候,一定要遵循Java规范。
@Data @NoArgsConstructor @AllArgsConstructor public class Computer { private Integer id; private String name; }
//@EqualsAndHashCode(callSuper = true) @Data @NoArgsConstructor @AllArgsConstructor public class AppleComputer extends Computer { private long price; private String color; public AppleComputer(Integer id, String name, long price, String color) { super(id, name); this.price = price; this.color = color; } }
/** * <h2>lombok 的第二个坑</h2> * */ private static void equalsAndHashCodeBug() { AppleComputer computer1 = new AppleComputer( 1, "Mac Pro", 1L, "yellow" ); AppleComputer computer2 = new AppleComputer( 2, "Mac Air", 1L, "yellow" ); System.out.println(computer1.equals(computer2));//@data注解会重写equals方法,所以这里就可以直接使用比较 //运行返回true????我们查看target方法,发现重写的euqals方法只判断了price和color属性,就需要使用@EqualsAndHashCode(callSuper = true)这个注解就是判断是否需要在子类的equals方法中加入父类的判断,默认值是false,所以没有比较父类的属性