【问题标题】:Element's equality check from list of object从对象列表中检查元素的相等性
【发布时间】:2014-11-14 09:51:18
【问题描述】:

我有一个 ListEmployee 对象。

class Employee{  
  private int empId;  
  private String name;  
}  

现在我有

List<Employee> empList = new ArrayList<Employee>();  

如果我的列表中包含一个名为“ABC”的员工,我该如何找到??
empList.contains("ABC"); 不会工作...

我应该把它放在Map吗?哪个效率更高??

只是想提一下,我从数据库中获取了我的 Employee 对象....

【问题讨论】:

  • Employee 怎么可能等于 String
  • 您没有为empIdname 声明类型。可能你想要private int empId;private String name;
  • @afzalex - 谢谢......一个错字......实际上我已经做了一个场景来模拟我的问题
  • 只是想让大家知道,我从数据库中获取了我的 Employee 对象,在这种情况下,我将无法从 new 关键字创建新的 Employee 对象。

标签: java list arraylist collections


【解决方案1】:

你可以使用

Map<String, Employee> map = new HashMap<>();
map.put("ABC", new Employee("ABC"));
map.put("John", new Employee("John"));

然后检查

map.containsKey("ABC")


我应该把它放在地图上吗?哪个效率更高??

因为contains()的list方法,调用indexOf,需要遍历所有元素 像这样

public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}

地图不需要遍历所有元素

【讨论】:

  • 不要覆盖等于检查包含...而是添加一个新方法来检查它是否包含。当需要以不同的方式进行相等检查时,覆盖 equals。你从哪里得到地图?
  • 我应该把它放在地图上吗?哪个效率更高??由 OP 发布
【解决方案2】:

由于您将Employee 对象而不是String 存储在列表中,我认为如果不遍历所有列表对象就不可能进行搜索

for (Employee employee : empList) {
      if (employee.getName().equals(searchString))
        System.out.println("Found");
    }

注意:您的 Employee 类应该通过 getter 方法或将其更改为 public 来访问 name 字段


还有其他选择,但这取决于您的要求以及速度、空间、可读性、资源等之间的权衡

我能想到的一件事是HashMap,里面有constant time lookup in average case

HashMap<Integer, String> hm = new HashMap<Integer, String>();
hm.put(1, "Tom");
System.out.println(hm.containsValue("Tom"));

现在,

我应该把它放在地图上吗?哪个效率更高??

而不是编码和分析,Know Thy Complexities 事先!

【讨论】:

  • 我曾尝试过使用迭代器的相同方式......但我在想,如果有更好的方法来做到这一点。仅供参考 - 我有 getter setter...
【解决方案3】:

在 Java 8 中,如果您想确定员工列表是否包含名为“ABC”的员工,您可以这样做:

boolean containsABC = empList.stream().anyMatch(emp -> emp.getName().equals("ABC"));

【讨论】:

    【解决方案4】:

    覆盖等于。然后你可以使用 List.contains

    class Employee {  
        private empId;  
        private name;
        public boolean equals(Object o) {
            return (o instanceof Employee && ((Employee)o).empId == empId && ((Employee)o).name = name);
        }
    }  
    


    List l = ...;
    Employee e = new Employee(...);
    l.add(e);
    l.contains(e);
    

    【讨论】:

    • ControlAltDel, l.contains(e) 将返回 true,即使您没有覆盖 equals(...) 方法。
    • 仅当 Employee 对象是同一个对象时。使用 equals 可以匹配实际值
    • 我在考虑你的例子。
    • 这个答案是正确的。看看这个问题,OP已经编辑了它。 @brso05。如果用户创建具有相同 ID 和名称的 Employee 的新对象,contains(e) 将不会返回 true。
    【解决方案5】:

    这是您可以使用的代码。 我正在考虑您希望 list 在 empIdnameEmployee 匹配时返回 true。
    我也更喜欢在您的代码中使用构造函数(只是推荐)。
    以下代码将按照您的意愿运行。

    class Employee {
    
        private int empId;
        private String name;
    
        // below overriden function will return true if it found Employee with 
        // same ID and name
        @Override
        public boolean equals(Object obj) {
            return (obj instanceof Employee             //Checking instace of obj
                && ((Employee)obj).empId == empId       //Checking empId
                && ((Employee)obj).name.equals(name));  //Checking name
        }
    
        // Used constructor to create Employee
        Employee(int id, String nm) {
            empId = id;
            name = nm;
        }
    
    }
    


    这是一个运行示例:

    List l = new ArrayList();
    l.add(new Employee(1, "ME");
    System.out.println(l.contains(new Employee(1, "ME")));  //print true
    

    我还要感谢您,当您决定根据 设计模式 覆盖 equals(...) 方法时,您也应该覆盖 hashCode()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2022-08-22
      • 2015-07-19
      • 2013-09-19
      相关资源
      最近更新 更多