簡體   English   中英

根據框架提供的不可編輯對象類的屬性在 HashSet 中添加唯一元素

[英]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 映射到包含empemp2的鍵"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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM