您的位置:首页 > 编程语言 > Java开发

List去重:根据集合中对象特定属性去重(2)

2018-01-22 21:52 344 查看
说明:第一篇我们使用HashSet,也即是HasMap的数据结构实现的去重,这里面有几个问题:1.性能问题,在去重的过程中创建了不必要的过渡对象,实际的效率会有所降低;2.对实体类有侵入,为了覆盖hashcode和equals方法,我们写了抽象类来实现这部分代码并设置去重属性,那么所要去重的实体类必须继承自这个抽象类;3.无法实现两个对象在我的定义下等价时的取舍,也就是去重的对象我们没办法控制;4.List原有的顺序被打乱了。

思路:如果能够在对原有集合进行遍历的过程中,遇到相同的对象,根据我们给定的规则取舍,应该会是一个相对较好的解决方式。

实现:

1.写一个接口,用来给定当我们遇到两个对象时,应该抛弃哪一个;返回null时不移除

public interface ReduceComparable<T> {

//返回值是我们抛弃的对象,有可能是t1,也可能是t2,根据需求自行实现
T compare(T t1, T t2);

}

2.写一个类,用来执行List的去重逻辑;对传入的list进行反向两层遍历,一旦遇到相同的,则从list中删除1中规则返回的对象,并从内层循环中跳出,接着执行下一次外层循环,这一次外层循环的size一定要是list当前的size;遍历结束之后,所有重复的对象都会按照我们的规则移除,并且在这个过程中没有任何新的中间对象产生;经过对比,这种方法的效率大约是采用Set去重方法的20倍以上;

public class ListReducer<T> {

private ReduceComparable<T> reduce;

public ListReducer(ReduceComparable<T> reduce) {
this.reduce = reduce;
}

private void checkReduce() {
if (reduce == null)
throw new RuntimeException("ListReducer need a ReduceComparable to do reduce!");
}

public void reduce(List<? extends T> list) {
checkReduce();
for (int i = list.size() - 1; i >= 0; i--) {
for (int j = i - 1; j >= 0; j--) {
T vehicle1 = list.get(i);
T vehicle2 = list.get(j);
T obj = reduce.compare(vehicle1, vehicle2);
if (obj != null) {
list.remove(obj);
break;
}
}
}
}
}

3.实体类,此时的实体类无需进行任何修改;

public class Vehicle {

private String plateNumber;

private String model;

private String color;

private int size;

public int getSize() {
return size;
}

public void setSize(int size) {
this.size = size;
}

public String getPlateNumber() {
return plateNumber;
}

public void setPlateNumber(String plateNumber) {
this.plateNumber = plateNumber;
}

public String getModel() {
return model;
}

public void setModel(String model) {
this.model = model;
}

public String getColor() {
return color;
}

public void setColor(String color) {
this.color = color;
}

@Override
public String toString() {
return "Vehicle [plateNumber=" + plateNumber + ", model=" + model + ", color=" + color + ", size=" + size + "]";
}

}

4.可以根据自己需求实现ReduceComparable接口,这里简单实现一个;如果两个vehicle的color一样,那么谁的size大抛弃哪一个,即保留size小的;

public class VehicleReduce implements ReduceComparable<Vehicle>{

@Override
public Vehicle compare(Vehicle vehicle1, Vehicle vehicle2) {
if(vehicle1.getPlateNumber().equals(vehicle2.getPlateNumber())) {
if(vehicle1.getModel().equals(vehicle2.getModel())) {
if (vehicle1.getColor().equals(vehicle2.getColor())) {
if (vehicle1.getSize() > vehicle2.getSize()) {
return vehicle1;
} else {
return vehicle2;
}
}
}
}
return null;
}

}

5.简单调用一下;

public static void main(String[] args) {

String originJson = "[{\"plateNumber\":\"京A00001\",\"model\":\"tesla90\",\"color\":\"black\",\"size\":12},"
+ "{\"plateNumber\":\"京A00002\",\"model\":\"tesla90\",\"color\":\"black\",\"size\":11},"
+ "{\"plateNumber\":\"京A00001\",\"model\":\"tesla90\",\"color\":\"black\",\"size\":17}]";

List<Vehicle> list = JSONArray.parseArray(originJson, Vehicle.class);

System.out.println("before: " + list);

ListReducer<Vehicle> listReducer = new ListReducer<>(new VehicleReduce());
listReducer.reduce(list);

System.out.println("after: " + list);
}

按照4中的实现,应该会在前三个字段都一致时,保留size小的;程序的执行结果如下:
before: [Vehicle [plateNumber=京A00001, model=tesla90, color=black, size=12], Vehicle [plateNumber=京A00002, model=tesla90, color=black, size=11], Vehicle [plateNumber=京A00001, model=tesla90, color=black, size=13]]

after: [Vehicle [plateNumber=京A00001, model=tesla90, color=black, size=12], Vehicle [plateNumber=京A00002, model=tesla90, color=black, size=11]]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  json 去重 java