【问题标题】:Retain non-duplicated entries in lists保留列表中不重复的条目
【发布时间】:2020-10-21 20:40:34
【问题描述】:

我有对象列表。假设object的结构如下。

class Test {
   Int id;
   String y;
}

给定一个包含四个 Test 实例的列表“testList”(我们称它们为 t1、t2、t3、t4)。

要求是获得一个列表,其中仅保留字段“y”唯一的项目。 应删除具有重复值的每个条目。

在上述情况下,假设 t3 和 t4 包含相同的 'y' 值,结果应该是 t1 和 t2。

一种解决方案是首先创建一个哈希映射:

  Map<String, List<Test>> yTestMap = new HashMap();

并使用字段作为键,添加与键匹配的每个对象

然后循环遍历 HashMap 条目集,如果值列表包含多个元素,则从实际列表中删除这些 Test 实例。

for (List<Test> duplicateTestList : yTestMap.values())   
{                
     testList.removeAll(duplicateTestList);
}

您能否建议一种更简洁的方法,也许使用 Java 8 流?

【问题讨论】:

  • 您正试图通过键 yTest 对象列表中查找不同的值。最初的问题应该可以帮助您了解如何在一个流中实现相同的目标。不过,您分享的方法也很有效。
  • @Naman:感谢您的评论。我的问题与获得不同的价值观无关。在我的情况下,如果任何值重复,则根本不应该包含它。
  • 在遍历初始输入时不改变结果列表,那么这在单次迭代中是不可能的。此外,在您创建了一个分组的Map(例如Map&lt;String, List&lt;Test&gt;&gt; yTestMap)之后,管道可以只对带有entry.getValue().size()==1 的条目进行迭代以提供响应。另外,忘了效率吧,当前的removeAll 会从testList 中删除所有元素,所以在功能上似乎也不正确。
  • 我想指出的内容与实现中的List&lt;Test&gt; testList; //input list List&lt;Test&gt; yTestResult = testList.stream() .collect(Collectors.groupingBy(Test::getY)) .entrySet().stream() .filter(e -&gt; e.getValue().size() == 1) .flatMap(e -&gt; e.getValue().stream()) .collect(Collectors.toList()); 相似,其中groupingBy 产生与Map 相似的输出,并且进一步的管道仅选择唯一对象。
  • 这是个好问题。我有同样的问题。标题应该以某种方式改写。 @Naman 的答案应该被认为是正确的答案恕我直言。

标签: java data-structures collections java-8


【解决方案1】:

您可以使用 Set 和 Comparable。 在使用它之前,您应该在 Test 中实现 Comparable。

import java.util.*;

public class Test implements Comparable<Test>{
 private int id;
 private String y;

 @Override
 public int compareTo(Test test){
   return y.compareTo(test.getY());
 }

 public void setY(String newY){
   y = newY;
 }

 public void setId(int newId){
   id = newId;
 }

 public String getY(){
   return y;
 }

 public String toString(){
  return "Id: " + id + "\nValue of Y: " + y + "\n";
 }
}

Set 中不允许有重复值。

import java.util.*;

public class Main{

 public static void main(String arg[]){
    Set<Test> testList = new TreeSet<Test>();

    Test t0 = new Test();
    t0.setId(0);
    t0.setY("Y0");

    Test t1 = new Test();
    t1.setId(1);
    t1.setY("Y1");

    Test t2 = new Test();
    t2.setId(2);
    t2.setY("Y1");//here you can see same 'Y' value of t1 

    testList.add(t0);
    testList.add(t1);
    testList.add(t2);

    //t0 and t1 will be printed. t2 has duplicated Y-value so it's 
    // not included  
    testList.forEach(e -> System.out.println(e));
}

}

【讨论】:

    【解决方案2】:

    使用流你可以做到:

            List<Test> data = Arrays.asList(new Test(0, "a"),
                    new Test(1, "b"),
                    new Test(2, "c"),
                    new Test(3, "c"));
            List<Test> answer = data.stream()
                    .collect(Collectors.groupingBy(t -> t.y())) // Group by 'y'
                    .entrySet().stream() // Stream of (key, value) pairs, value is a list of "Test"s
                    .filter(kv -> kv.getValue().size() == 1) // Only those with one element
                    .map(kv -> kv.getValue().get(0)) // Take the first element
                    .collect(Collectors.toList());
            System.out.printf("In: %s\nOut: %s\n", data, answer);
    
    

    输出是:

    In: [Test[id=0, y=a], Test[id=1, y=b], Test[id=2, y=c], Test[id=3, y=c]]
    Out: [Test[id=0, y=a], Test[id=1, y=b]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      相关资源
      最近更新 更多