【问题标题】:Java - how to delete elements with the same property value from collection?Java - 如何从集合中删除具有相同属性值的元素?
【发布时间】:2015-03-24 15:37:56
【问题描述】:

假设有一个带有 SomeField 属性的 SomeClass 元素的集合。如何从此 Collection 中删除具有等效 SomeField 属性的重复元素并仅保留一个具有该 SomeField 值的元素?

【问题讨论】:

  • 我为你准备了三个词——iterator、getter、for(Type obj:list)
  • 看看java.uti.Set。

标签: java algorithm list collections


【解决方案1】:

您需要为 SomeClass 实现 hashCode 和 equals,以便只考虑 SomeField。

class SomeClass {
  private SomeField field;
  public int hashCode() {
    return field.hashCode();
  }
  public boolean equals(Object o) {
    if (o instanceof SomeClass == false){
      return false
    }
    SomeClass someClass = (SomeClass)o;
    return someClass.field.equals(this.field)

  }
}

现在您可以将所有内容放入 Set 以删除重复项

Set set = new HashSet(collection);

【讨论】:

    【解决方案2】:

    Java 集合有一个可选 remove 方法。假设您正在处理的集合支持它,您可以使用它:

    boolean remove(Object o)

    从该集合中移除指定元素的单个实例(如果存在)(可选操作)。

    假设集合有一个add 方法,您可以运行一个循环,当它存在时从集合中删除元素(使用contains 检查),一旦它没有元素add 它。

    while(myCollection.contains(el)){
        myCollection.remove(el);
    }
    myCollection.add(el);
    

    再说一遍 - 最好从集合中创建一个 Set(例如,通过将其传递给 TreeSet 构造函数) - 保证每个元素只有一个实例。

    Set unique = new TreeSet(myCollection); // assumes comparable
    Set unique2 = new HashSet(myCollection); // assumes hashCode
    

    【讨论】:

      【解决方案3】:

      使用Map

      将所有内容转储到由SomeField 键入的Map(假设SomeField 已明确定义equalshashCode)然后使用Map.values

      如果您想保留遇到的最后个重复:

      final Collection<SomeClass> filtered = list.stream()
              .collect(Collectors.toMap(SomeClass::getKey, identity()))
              .values();
      

      或者,如果您想反击第一个重复:

      final HashMap<Integer, SomeClass> mapped = list.stream()
              .collect(HashMap::new, (m, s) -> m.merge(s.getKey(), s, (l, r) -> l), HashMap::putAll);
      final Collection<SomeClass> filtered = mapped.values();
      

      第二种情况,类型推断系统需要一点帮助,所以需要分配中间的Map

      【讨论】:

        【解决方案4】:

        Collections 类没有直接的remove 方法。你可以实现Collection接口和实现remove方法,或者使用其他实现之一(LinkedList、Set、ArrayList等);

        以下是伪代码,但您可以根据自己的需要进行调整:

        Collection<YourType> list = new ArrayList<>();
        
        // Add your objects to it - to make your collection
        for (YourType T: ArrayOfYourType)
            list.add(T);
        
        // Remove elements from the list
        
        for (YourType T: list)
            if T.getSomeProps() == equals(your_val){  // Or equals()
                list.remove(T);
            }
        

        您也可以使用地图对列出它们,但这可能对您正在尝试做的事情有点过头了。

        【讨论】:

          【解决方案5】:

          有一些简单的方法可以解决这个问题。

          如果SomeField 值是SomeClass 的唯一成员,那么您可以根据SomeField 轻松覆盖SomeClass 中的hashCodeequals,然后只需将您的原始集合添加到HashSet .

          如果不是这种情况并且SomeClass 更复杂,您仍然可以使用Set。但是,您需要以某种方式过滤掉重复项,一种好的方法是使用ComparatorTreeSet

          // Create a new Set with a specified comparator
          final Collection<SomeClass> someClasses = 
                  new TreeSet<>(Comparator.comparing(SomeClass::getSomeField));
          
          // Add all elements from the original collection (duplicates will be removed)
          someClasses.addAll(originalColl);
          

          Comparator.comparing 方法创建一个Comparator。如果您不使用 Java 8,也可以使用非 lambda Comparator

          Comparator<SomeClass> comparator = new Comparator<SomeClass>() {
              @Override
              public int compare(final SomeClass o1, final SomeClass o2) {
                  // Do some kind of compare-operation. If SomeField is 
                  // Comparable you can do it this way:
                  return o1.getSomeField().compareTo(o2.getSomeField());
              }
          }
          

          【讨论】:

          • 虽然这可行,但值得指出的是,这是假设SomeField implements Comparable&lt;SomeField&gt;。此外,TreeSet 具有 O(lg n) add 复杂性,如果正在处理大量数据,这可能是一个问题。相反,HashSet 具有 O(1) add
          • @BoristheSpider,正确。完全取决于要处理的数据量。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-09-04
          • 2018-04-19
          • 1970-01-01
          • 2020-06-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多