List去重:根据集合中对象特定属性去重(2)
2018-01-22 21:52
344 查看
说明:第一篇我们使用HashSet,也即是HasMap的数据结构实现的去重,这里面有几个问题:1.性能问题,在去重的过程中创建了不必要的过渡对象,实际的效率会有所降低;2.对实体类有侵入,为了覆盖hashcode和equals方法,我们写了抽象类来实现这部分代码并设置去重属性,那么所要去重的实体类必须继承自这个抽象类;3.无法实现两个对象在我的定义下等价时的取舍,也就是去重的对象我们没办法控制;4.List原有的顺序被打乱了。
思路:如果能够在对原有集合进行遍历的过程中,遇到相同的对象,根据我们给定的规则取舍,应该会是一个相对较好的解决方式。
实现:
1.写一个接口,用来给定当我们遇到两个对象时,应该抛弃哪一个;返回null时不移除
2.写一个类,用来执行List的去重逻辑;对传入的list进行反向两层遍历,一旦遇到相同的,则从list中删除1中规则返回的对象,并从内层循环中跳出,接着执行下一次外层循环,这一次外层循环的size一定要是list当前的size;遍历结束之后,所有重复的对象都会按照我们的规则移除,并且在这个过程中没有任何新的中间对象产生;经过对比,这种方法的效率大约是采用Set去重方法的20倍以上;
3.实体类,此时的实体类无需进行任何修改;
4.可以根据自己需求实现ReduceComparable接口,这里简单实现一个;如果两个vehicle的color一样,那么谁的size大抛弃哪一个,即保留size小的;
5.简单调用一下;
按照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]]
思路:如果能够在对原有集合进行遍历的过程中,遇到相同的对象,根据我们给定的规则取舍,应该会是一个相对较好的解决方式。
实现:
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]]
相关文章推荐
- List去重:根据集合中对象特定属性去重(1)
- List集合中的对象根据属性排序
- Java面试题,List集合中根据对象的某一属性排序
- 如何根据对象的属性,对集合(list / set)中的对象进行排序
- List集合根据存储对象的属性字段排序实现
- List集合中的对象根据属性排序
- List<T>泛型集合根据对象的某一属性排序
- List集合中的对象根据属性排序
- List集合中删除属性(一个或者多个属性)相同的对象返回List且根据对象属性进行排序输出
- list集合根据对象属性排序举例
- List集合中的对象根据属性排序
- List集合中的对象根据属性排序
- 对象集合list根据对象属性排序2015-8-16
- C#中对List<Object>泛型集合,根据对象的某一属性进行升序排序
- 如何根据对象的属性,对集合(list / set)中的对象进行排序
- List集合中的对象根据属性排序
- List集合中的对象根据属性排序
- List集合中的对象根据属性排序
- List集合中的对象根据属性排序
- java List集合中的对象根据属性降序/升序排序