【问题标题】:Best way to implement a Pair class in Java在 Java 中实现 Pair 类的最佳方法
【发布时间】:2021-05-27 04:08:33
【问题描述】:

我使用 Map.Entry 为 Java 中的 Pair 类编写了以下代码。有没有人有任何改进它的建议?对我来说,该类需要满足的最重要标准是构造 Pair 很容易,并且 .equals 可以按照我想要的方式工作(Pair 中的两个对象以相同的顺序相等意味着对)。该代码似乎按预期运行,并且尚未用于任何占用我系统内存的内容,但我们将不胜感激。

import java.util.*;

public class Pair {
    // Return a map entry (key-value pair) from the specified values
    public static <T, U> Map.Entry<T, U> of(T first, U second) {
        return new AbstractMap.SimpleEntry<>(first, second);
    }

    private Map.Entry entry;

    public Pair (Object x, Object y) {
        Set<Map.Entry> entries = new HashSet<>();
        entries.add(Pair.of(x, y));
        Object[] setArray = entries.toArray();
        this.entry = (Map.Entry) setArray[0];
    }

    public Object getKey() {
        return entry.getKey();
    }
    public Object getValue() {
        return entry.getValue();
    }


    @Override
    public boolean equals(Object o)
    {
        if (o instanceof Pair) {
            Pair pair = (Pair) o;
            return ( (entry.getKey().equals(pair.getKey())) && (entry.getValue().equals(pair.getValue())) );
        }
        return false;
    }

    @Override
    public int hashCode() {
            return Objects.hash(entry.getKey(), entry.getValue());
    }

    @Override
    public String toString() {
            return String.format( "(" +entry.getKey().toString() + ", " + entry.getValue().toString() + ")" );
    }
}

我一直在考虑使用 Collections.singletonMap 而不是 Map.Entry。

到目前为止,我已经使用以下代码成功测试了我的代码:

import java.util.HashMap;

public class Main {

    public static void main(String[] args) {
        HashMap<Pair, Integer> testMap = new HashMap<>();
        Pair onThrup = new Pair(1, 3);
        System.out.println(onThrup); //Prints contents of Pair, not hash
        testMap.put(onThrup, 7);
        Pair unoTres = new Pair(1, 3);
        System.out.println(onThrup.equals(unoTres));
        System.out.println(testMap.containsKey(onThrup));
        System.out.println(unoTres.hashCode() == onThrup.hashCode());
        System.out.println(testMap.containsKey(unoTres)); // Should be, and is, true
    }
}

【问题讨论】:

  • 我确实希望能够运行一个构造新 Pairs 的循环,同时重复使用相同的变量名,如 p,而不会出现问题。 .equals() 下的哈希相等和相等应该基于 Pair 的内容,以便在新 Pair 上运行 HashMap.containsKey 将返回 true,如果它与作为键添加的 Pair 具有相同的值之前的 HashMap 的键值对。我相信我这里的代码确实可以做到这一点,但是如果有人对格式或效率有建议,可能会有更好的方法来编写类。
  • 我认为您可以为该对必须持有的每个对象使用一个字段。它将消除对 Map.Entry 的需要。您还可以使用泛型来制作您的类签名,例如Pair&lt;T1, T2&gt;。无论如何,我真的不明白你为什么使用成对构造函数中的集合。可以简化。
  • 如果您希望它可用作映射键,则必须覆盖 Pair 类中的 equals 和 hashCode 方法。需要了解的可以看this tutorial
  • 您还可以使用第三方 Pair 实现 - 来自 Apache Commons 的 ImmutablePair 或来自 Vavr 的 Tuple2
  • 我使用了 Set,因为 Entry 是抽象的,无法实例化。我相信 hashCode 和 equals 的覆盖是成功的。

标签: java tuples


【解决方案1】:

Java 16 包括 Record Classes:

public record Pair<K, V>(K key, V value) {
    // intentionally empty
}

创建一个,其中包含最终字段、检索keyvalueequalshashCodetoString 方法的方法。

使用示例:

var one = new Pair<Integer, String>(1, "one");
var two = new Pair(2, "two");
System.out.println(one);   // Pair[key=1, value=one]
if (!one.equals(two))
    System.out.printf("not same as Pair for %d%n", two.key());

不确定什么是最好的,如果有的话(java 16)我会用那个

JLS 8.10
JEP 395

【讨论】:

    猜你喜欢
    • 2013-10-23
    • 2023-04-07
    • 1970-01-01
    • 2011-11-11
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-04
    相关资源
    最近更新 更多