【问题标题】:is there a faster way to extract unique values from object collection?有没有更快的方法从对象集合中提取唯一值?
【发布时间】:2013-08-01 00:06:28
【问题描述】:

我有一种方法可以从作为员工信息的对象集合中提取值:

public class Employee
{
    public String AREA;
    public String EMPLOYEE_ID;
    public String EMPLOYEE_NAME;
}

我想获得我认为更容易的所有不同区域,只需检查 ArrayList 是否包含该值,如果不是添加它,则需要 187 毫秒才能完成,:

    long startTime = System.currentTimeMillis();
    ArrayList<String> distinct_areas = new ArrayList<String>();
    for (int i = 0; i < this.employeeTress.length; i++)
    {
        if (!distinct_areas.contains(this.employeeTress[i].AREA))
            distinct_areas.add(this.employeeTress[i].AREA);
    }
    String[] unique = new String[distinct_areas.size()];
    distinct_areas.toArray(unique);
    long endTime = System.currentTimeMillis();
    System.out.println("Total execution time: " + (endTime - startTime) + "ms");

然后我想用不同的方法来看看它是否变得更快,对数组进行排序,然后只检查最后一项,如果它不同,然后添加它,它会更快一点,它需要 121 毫秒才能完成:

    startTime = System.currentTimeMillis();
    String[] vs = new String[this.employeeTress.length];
    for (int i = 0; i < this.employeeTress.length; i++)
    {
        vs[i] = this.employeeTress[i].AREA;
    }
    Arrays.sort(vs);
    ArrayList<String> vsunique = new ArrayList<String>();
    vsunique.add(vs[0]);
    for (int i = 0; i < vs.length; i++)
    {
        if (!vsunique.get(vsunique.size()-1).equals(vs[i]))
        {
            vsunique.add(vs[i]);
        }
    }
    String[] uni = new String[vsunique.size()];
    vsunique.toArray(uni);
    endTime = System.currentTimeMillis();
    System.out.println("Total execution time: " + (endTime - startTime) + "ms");

我是 Java 新手,我想知道一种更好的方法来做到这一点。 *注意,此代码应在 android 姜饼 API LVL 10 中工作 问候。

【问题讨论】:

  • 使用Set 而不是List。另外,我不会为此担心性能改进直到它证明是应用程序中的真正瓶颈。
  • Java 中唯一应该全部大写的类型是final static 原语或enums。
  • @Dukeling 这包括 JAVA 语言本身的名称 :))
  • 对于所有大写字段,该类是从提取表单中复制粘贴的一个 json 结构,该结构具有来自 ORM 的所有大写字段,并从 Oracle 数据库自动创建表,换句话说,我没有键入它们。
  • 如果这是一个 ORM,你不能做一些事情来通过 ORM 获得不同的区域吗?

标签: java collections


【解决方案1】:

如果要获取或计算员工列表中的不同区域,可以使用一组字符串。我正在更改变量名称以匹配 Java 标准。之后你可以得到计数。理想情况下,这些将是惰性方法。

命令式代码

public Set<String> areas(final List<Employee> employees) {
    Set<String> areas = new HashSet<>();
    for(final Employee employee: employees) {
        areas.add(employee.getArea());
    }
    return areas;
}

功能代码(谷歌番石榴)

public Set<String> areas(final List<Employee> employees) {
    return Sets.newHashSet(
        Lists.transform(employees, new Function<Employee, String>() {
            public String apply(Employee e) {
                return e.getArea();
            }
        }));
}

Lambda (Java 8)

public Set<String> areas(final List<Employee> employees) {
    return new HashSet<String>(employees.map(e => e.getArea()));
}

【讨论】:

  • 使用 HashSet 的命令式形式比检查项目是否已经在集合中要快得多。谢谢你。
  • 那是因为 JRE 也在做同样的事情。其他版本只是删除了显式循环。他们不会给你买那么多,因为这不是一个懒惰的问题。你需要计算整个事情。不过,您应该考虑其他存储数据的方式。关系数据库可以存储您的员工,并且通过适当的索引,数据库可以非常快速地工作。我确实修正了一个错字。
【解决方案2】:

您可以使用 Set 来执行此操作,正如其他人已经说过的那样,但是如果您希望项目在具有相同 AREA 时被视为相等,那么您需要在 @987654325 中覆盖 equals 方法@object 使其基于该变量与其他对象进行比较。

在重写 equals 方法之前,您需要知道一些事情。这里有一个讨论: What issues should be considered when overriding equals and hashCode in Java?

【讨论】:

    【解决方案3】:

    将所有员工插入HashSet。从Set 的定义来看,它们都是唯一的。

    Set<Employee> unique = new HashSet<Employee>(Arrays.asList(employeeTress));
    // unique.toArray() if needed
    

    如果您希望Employee 对象在具有相同AREA 时被视为相等,则需要properly 覆盖equals() 类中的equals() 方法。

    【讨论】:

      【解决方案4】:

      只需使用 HashSet,它会仅向 HashSet 添加唯一元素.

      HashSet的objectOfHashSet.add(Object)函数会返回true on successful添加的对象,

      Set<Employee> hs = new HashSet<Employee>();
      
          if(!hs.add(i2)){
            // do some operation here
          }
      

      您还需要在此处覆盖equals method

      public boolean equals(Object obj) {
              if (obj == null)
                  return false;
              if (obj == this)
                  return true;
              if (!(obj instanceof Employee))
                  return false;
      
              // HERE PERFORM YOUR CHECK
              if("Employee.NAME".isequals(obj.NAME))
              {return true;}
          }
      

      还要确保当对象在集合中时,您放入集合中的hashCode() of the key objects 永远不会更改。确保这一点的最佳方法是让您的keys immutable

      【讨论】:

      • 事实上,Set 应该是保存Employee 数据而不是当前数组 OP 使用的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      相关资源
      最近更新 更多