[英]Add unique elements in HashSet based on attributes of framework provided non-editable object classes
我正在嘗試生成一個包含唯一Employee
實例的HashSet
。 應根據對象屬性建立唯一性。
問題是我最終得到了重復項。
請注意, Employee
類是由框架提供的,不可能為equals()
和hashCode()
提供自定義實現。
Employee
類:
public class Employee {
private long employeeId;
private String name;
// getters, setters
@Override
public String toString() {
return "Employee{" +
"employeeId=" + employeeId +
", name='" + name + '\'' +
'}';
}
}
Map<String, Set<Employee>> ackErrorMap = new HashMap<>();
Employee emp = new Employee(1,"bon");
Employee emp2 = new Employee(1,"bon");
ackErrorMap.computeIfAbsent("key1",
x -> new HashSet<>()).add(emp);
ackErrorMap.computeIfAbsent("key1",
x -> new HashSet<>()).add(emp2);
這將導致 Set 映射到包含emp
和emp2
的鍵"key1"
,盡管對象屬性相同。
有什么辦法可以丟棄name
Employee
嗎? 還是使用ArrayList
會更好?
使用Arraylist
的可能示例
ackErrorMap.computeIfAbsent("key1",
x -> new ArrayList<>()).add(emp);
您可以覆蓋 Employee 類中的 equals 和 hashCode 方法。 如果兩個對象被認為相等,equals 方法應該返回 true,而 hashCode 方法應該為兩個被認為相等的對象返回相同的值。
class Employee {
private int id;
private String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return id == employee.id &&
Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
通過這些更改,當您將 emp 和 emp2 添加到 HashSet 時,只會添加其中一個,因為根據 equals 方法,它們將被視為相等。
您需要在 Employee 類中覆蓋 equals() 和 hashCode() 。 或者您可以在 Employee 類中使用 lombok 的 @EqualsAndHashCode 注釋。
您可以創建一個自定義類型來包裝來自框架的類,並根據您的要求實施equals/hashCode
協定。
這就是這種包裝器的樣子(為了簡潔起見,我使用的是Java 16 record
,但它也可以作為一個class
來實現)。
public record EmployeeWrapper(Employee employee) {
@Override
public boolean equals(Object o) {
return o instanceof EmployeeWrapper other
&& employee.getName().equals(other.employee.getName());
}
@Override
public int hashCode() {
return Objects.hash(employee.getName());
}
}
您可以使用類型為Map<String,Set<EmployeeWrapper>>
的 Map 來確保基於name
屬性的Employee
的唯一性。
我還建議更進一步,將 Map 封裝到一個class
中,該類將公開涵蓋與 Map 交互的所有場景的方法(例如添加新條目、按鍵獲取員工等),這樣您的客戶就不會撥號包裝器,但僅限於員工,包裝和解包將在封閉類中發生。
以下是它的實現方式:
public class AcrErrors {
private Map<String, Set<EmployeeWrapper>> ackErrorMap = new HashMap<>();
public void addEmployee(String key, Employee employee) {
EmployeeWrapper wrapper = new EmployeeWrapper(employee);
ackErrorMap
.computeIfAbsent(key, x -> new HashSet<>())
.add(wrapper);
}
public List<Employee> getEmployees(String key) {
return ackErrorMap.getOrDefault(key, Collections.emptySet()).stream()
.map(EmployeeWrapper::employee)
.toList();
}
// other methods
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.