当前位置: 首页 > 知识库问答 >
问题:

使用自定义hashCode的HashSet

鲜于华容
2023-03-14

您好,当我想在不更改hashCode()方法的情况下拥有一个自定义HashSet时,有人可以为我指出正确的方向。用法是拥有一组必须具有不同的一个(或多个)属性的对象。

例如,对于这个类:

@FieldDefaults(level = AccessLevel.PRIVATE)
@Getter @Setter
public class User{
    String name;
    String email;
    String age;
}

我希望有UserNameSet,它只允许包含具有不同名称的用户。我不想覆盖User中的hashCode和equals方法,因为我仍然想区分同名但不同电子邮件的用户。

我想为这一个HashMap重写hashCode()方法。

共有2个答案

上官和韵
2023-03-14

Commons集合已经提供了一个Equator接口来执行您的建议:

public interface Equator<T> {
    boolean equate(T o1, T o2);
    int hash(T o);
}

但是,对基于赤道创建集合的直接支持是有限的。CollexiUtils中有一些涉及赤道的操作。

但是,您可以利用Transformer将所需的对象包装成使用赤道的对象,然后使用transformers提供的所有支持公共集合。例如,使用SetUtils。转换集:

class EquatorWrapper<T> {
    private final Class<T> clazz;
    private final T wrapped;
    private final Equator<T> equator;

    public EquatorWrapper(Class<T> clazz, T wrapped, Equator<T> equator) {
        this.clazz = clazz;
        this.wrapped = wrapped;
        this.equator = equator;
    }

    @Override
    public boolean equals(Object obj) {
        if (clazz.isInstance(obj)) {
            return equator.equate(wrapped, clazz.cast(obj));
        }
        return false;
    }

    @Override
    public int hashCode() {
        return equator.hash(wrapped);
    }
}

class EquatorTransformer<T> implements Transformer<T, Object> {
    private final Class<T> clazz;
    private final Equator<T> equator;

    public EquatorTransformer(Class<T> clazz, Equator<T> equator) {
        this.clazz = clazz;
        this.equator = equator;
    }
        
    @Override
    public Object transform(T input) {
        return new EquatorWrapper<>(clazz, input, equator);
    }
}

SetUtils.transformedSet(someSet, EquatorTransformer.of(someEquator, SomeClazz.clazz));
贝礼骞
2023-03-14

我想有UserNameSet,它只允许包含具有不同名称的用户

您可以应用组合并创建一个维护Map并将所有调用委托给它的类。

这种方法比扩展集合更灵活,也不那么乏味,而且不会创建紧密耦合。

class UserNameSet {
    private Map<String, User> userByName = new HashMap<>();
    
    public User add(User user) {
        return userByName.put(user.getName(), user);
    }
    
    public User remove(User user) {
        return userByName.remove(user.getName());
    }
    
    public User remove(String name) {
        return userByName.remove(name);
    }
    
    public boolean contain(String name) {
        return userByName.containsKey(name);
    }
    
    public boolean contain(User user) {
        return userByName.containsValue(user.getName());
    }
    
    // all other methods that are required
}
 类似资料:
  • 我有这样的记录: 它获取default和方法。 如何调整这些方法使其具有自定义行为?假设,我想忽略方法中的。

  • 本文向大家介绍定义hashcode时使用31系数的原因,包括了定义hashcode时使用31系数的原因的使用技巧和注意事项,需要的朋友参考一下 散列计算就是计算元素应该放在数组的哪个元素里。准确的说是放到哪个链表里面。按照Java的规则,如果你要想将一个对象放入HashMap中,你的对象的类必须提供hashcode方法,返回一个整数值。比如String类就有如下方法: 注意上面的for循环,有点搞

  • 问题内容: 建议和有时是必要的,即表示值(类 值类 )来覆盖,[和任选]的方法。这些方法返回的值取决于类及其超类的成员变量的全部或子集。为了实现它们正常,你必须了解理论的一点点 散列 和代数和集理论的一点点(不要太多,几乎一切都在explaind 的javadoc 这些方法和有效的Java形式乔希布洛赫。) 在大多数情况下,此方法的实现遵循一个模板,并且IDE(如Eclipse JDT)包括生成它

  • 假设我有一个名为的方法的接口,它接受了的参数。在中有名为和的字段。我想模拟调用此方法的响应,并返回不同的模拟响应结果,只要ServiceRequest中的值不同。 我有以下代码,如follow(参考https://www.baeldung.com/mockito-argument-matchers),但它返回空指针异常。这里出了什么问题?

  • 我发现了几个与此相关的(不是重复的)问题,但它们不能让我满意。 我无法理解在哪里以及为什么要使用? 我在一本书中读到了一个自定义注释的示例,但没有详细解释。 myMeth()内的输出与预期一致。 关于这个例子,我有几个问题。 1-如何在此程序中使用和?或

  • 我试图找出如何使用一个与一个在,但没有运气,我已经查了,我能找到的都是不完整的教程和问题。下面是我的FXML 还有我的模特 和我不完整的 还有我的控制器 请不要告诉我找不到。我现在迷路了,我不知道在我的FXML中更新图像视图和标签的正确方法。任何人来帮助或与一个教程的链接,我可以遵循,我将不胜感激。