问题背景
这两天遇到促销商品在数据库重复的问题,实在是有一点不好排查。现在也捞不到当时的日志,也不知道用户的操作。让人很是头大。所以,只能在插入数据库前对数据做一次去重,保证进入数据库是不重复的。
如何去重
我能想到的最快捷的方法就是直接把List抛给HashMap,这个时候我们就可以得到一个不重复的Set集合。然后在还原成List。
代码如下:
HashSet<Object> set=new HashSet<>();
那么,我们需要来考虑一下HashSet是如何保证不重复的。实际上看到这个名字,我们就知道其一定是基于Hash算法实现的。那么他在存储的时候实际上借助的还是一个HashMap。在存入对象的时候,会调用对象的hashCode()方法,两个对象的hashcode值是相等的,则判定两对象相等,于是乎只存在一个。当hashcode不相等的时候,还会去调用equals()方法。最终的判断两个对象是否相等。我们可以看得出来,如果想要我们的对象在HashSet中好好的存储。那我们必须自定义POJO的hashCode方法和equals方法。
自定义方法
在自定义方法的时候我按快捷键ctrl+o,按出来的可以重写的方法我竟然莫有找到。我勒个去!后来我在想是不是POJO头顶的注解的干扰。实际上我是用了lombok的@Data注解。我一直以为这个注解只是给POJO添加get以及set方法而已。谁知道,他竟然自己重写了那两个方法,所以导致我找不到。
于是我点进@Data的源代码。如下:
/**
* Generates getters for all fields, a useful toString method, and hashCode and equals implementations that check
* all non-transient fields. Will also generate setters for all non-final fields, as well as a constructor.
* <p>
* Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
* Complete documentation is found at <a href="https://projectlombok.org/features/Data.html">the project lombok features page for @Data</a>.
*
* @see Getter
* @see Setter
* @see RequiredArgsConstructor
* @see ToString
* @see EqualsAndHashCode
* @see lombok.Value
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
/**
* If you specify a static constructor name, then the generated constructor will be private, and
* instead a static factory method is created that other classes can use to create instances.
* We suggest the name: "of", like so:
*
* <pre>
* public @Data(staticConstructor = "of") class Point { final int x, y; }
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
*/
String staticConstructor() default "";
}
那我也就不必要去写如何重写hashCode以及equals方法了。但是大家要记住,如果你要用基于hash算法首先的集合,请一定要重写他们!
总结
总的来说,还是非常的有收获的。从一次去重得到的经验。看来我小看lombok了。下一篇想总结下lombok的常用注解。