【问题标题】:Get unique values from ArrayList in Java从 Java 中的 ArrayList 获取唯一值
【发布时间】:2012-11-05 22:01:55
【问题描述】:

我有一个ArrayList,其中包含许多记录,其中一列包含气体名称,如 CO2 CH4 SO2 等。现在我只想检索不同的气体名称(唯一),而不需要从 ArrayList 重复。怎么办?

【问题讨论】:

  • 我会更新标签。这是一个 Java 问题,我认为它与 jsf 和 primefaces 无关......

标签: java list set


【解决方案1】:

您应该使用SetSet 是不包含重复项的 Collection

如果您有一个包含重复项的 List,您可以获得这样的唯一条目:

List<String> gasList = // create list with duplicates...
Set<String> uniqueGas = new HashSet<String>(gasList);
System.out.println("Unique gas count: " + uniqueGas.size());

注意:此HashSet 构造函数通过调用元素的equals() 方法来识别重复项。

【讨论】:

  • 这意味着如果两个记录的名称相等,则认为 2 个记录是相等的(在 HashSet 的意义上)。
  • @njzk2 - 我认为这很明显,但我想我可以编辑明确指出...
  • 在尝试实现上述代码时出现错误:java: no suitable constructor found for HashSet。知道为什么会这样吗?
  • 如果您想保留列表中的原始订单,请参阅LinkedHashSetstackoverflow.com/a/8712770/32453
【解决方案2】:

您可以使用Java 8 Stream API

方法distinct 是一个中间操作,它过滤流并只允许不同的值(默认使用 Object::equals 方法)传递给下一个操作。
我在下面为您的情况写了一个示例,

// Create the list with duplicates.
List<String> listAll = Arrays.asList("CO2", "CH4", "SO2", "CO2", "CH4", "SO2", "CO2", "CH4", "SO2");

// Create a list with the distinct elements using stream.
List<String> listDistinct = listAll.stream().distinct().collect(Collectors.toList());

// Display them to terminal using stream::collect with a build in Collector.
String collectAll = listAll.stream().collect(Collectors.joining(", "));
System.out.println(collectAll); //=> CO2, CH4, SO2, CO2, CH4 etc..
String collectDistinct = listDistinct.stream().collect(Collectors.joining(", "));
System.out.println(collectDistinct); //=> CO2, CH4, SO2

【讨论】:

  • 标题大喊——“使用这个答案!不是公认的答案”。我必须说,这是要走的路。
  • 这个答案可能对大多数用途都很好,但如果您需要列表始终具有不同的值,例如在填充它时,那么我宁愿使用Set喜欢接受的答案。我可能一开始就没有List
【解决方案3】:

我希望我能正确理解您的问题:假设值的类型为 String,最有效的方法可能是转换为 HashSet 并对其进行迭代:

ArrayList<String> values = ... //Your values
HashSet<String> uniqueValues = new HashSet<>(values);
for (String value : uniqueValues) {
   ... //Do something
}

【讨论】:

    【解决方案4】:
    ArrayList values = ... // your values
    Set uniqueValues = new HashSet(values); //now unique
    

    【讨论】:

    • 我现在正在从列表中获取唯一元素,但它正在自行排序。但我需要数据不按排序顺序。如何完成?
    【解决方案5】:

    这是一种直接的方法,无需使用自定义比较器或类似的东西:

    Set<String> gasNames = new HashSet<String>();
    List<YourRecord> records = ...;
    
    for(YourRecord record : records) {
      gasNames.add(record.getGasName());
    }
    
    // now gasNames is a set of unique gas names, which you could operate on:
    List<String> sortedGasses = new ArrayList<String>(gasNames);
    Collections.sort(sortedGasses);
    

    注意:使用TreeSet 而不是HashSet 将给出直接排序的arraylist,上面的Collections.sort 可以被跳过,但TreeSet 在其他方面效率较低,因此使用@987654326 通常会更好,而且很少会更糟@即使需要排序。

    【讨论】:

      【解决方案6】:

      您可以使用它来制作唯一的列表

      ArrayList<String> listWithDuplicateValues = new ArrayList<>();
      list.add("first");
      list.add("first");
      list.add("second");
      
      ArrayList uniqueList = (ArrayList) listWithDuplicateValues.stream().distinct().collect(Collectors.toList());
      

      【讨论】:

        【解决方案7】:

        当我执行相同的查询时,我很难根据自己的情况调整解决方案,尽管之前的所有答案都有很好的见解。

        当必须获取唯一对象列表而不是字符串时,这是一种解决方案。 假设有一个 Record 对象列表。 Record 类只有String 类型的属性,没有int 类型的属性。 在这里实现hashCode() 变得很困难,因为hashCode() 需要返回一个int

        以下是Record 类的示例。

        public class Record{
        
            String employeeName;
            String employeeGroup;
        
            Record(String name, String group){  
                employeeName= name;
                employeeGroup = group;    
            }
            public String getEmployeeName(){
                return employeeName;
            }
            public String getEmployeeGroup(){
                return employeeGroup;
            }
        
          @Override
            public boolean equals(Object o){
                 if(o instanceof Record){
                    if (((Record) o).employeeGroup.equals(employeeGroup) &&
                          ((Record) o).employeeName.equals(employeeName)){
                        return true;
                    }
                 }
                 return false;
            }
        
            @Override
            public int hashCode() { //this should return a unique code
                int hash = 3; //this could be anything, but I would chose a prime(e.g. 5, 7, 11 )
                //again, the multiplier could be anything like 59,79,89, any prime
                hash = 89 * hash + Objects.hashCode(this.employeeGroup); 
                return hash;
            }
        

        正如其他人之前建议的那样,该类需要同时覆盖 equals()hashCode() 方法才能使用 HashSet

        现在,假设记录列表是allRecord(List&lt;Record&gt; allRecord)。

        Set<Record> distinctRecords = new HashSet<>();
        
        for(Record rc: allRecord){
            distinctRecords.add(rc);
        }
        

        这只会将不同的记录添加到哈希集 distinctRecords。

        希望这会有所帮助。

        【讨论】:

          【解决方案8】:
              public static List getUniqueValues(List input) {
                return new ArrayList<>(new LinkedHashSet<>(incoming));
              }
          

          别忘了先实现你的equals方法

          【讨论】:

            【解决方案9】:

            如果你有一个某种对象(bean)的数组,你可以这样做:

            List<aBean> gasList = createDuplicateGasBeans();
            Set<aBean> uniqueGas = new HashSet<aBean>(gasList);
            

            就像上面说的 Mathias Schwarz 一样,但是您必须为您的 aBean 提供 hashCode()equals(Object obj) 方法,这可以在 Eclipse 中通过专用菜单“Generate hashCode() and equals()”轻松完成(在 bean 类中)。 Set 将评估覆盖的方法以区分等于对象。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-17
              • 2011-05-14
              • 2019-05-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多