我喜欢Java有一个映射,你可以在映射中定义每个条目的类型,例如<String, Integer>。

我正在寻找的是一种类型的集合,其中集合中的每个元素都是一对值。对中的每个值都可以有自己的类型(如上面的String和Integer示例),该类型在声明时定义。

该集合将保持其给定的顺序,不会将其中一个值视为唯一键(就像在映射中一样)。

本质上,我希望能够定义一个数组类型<String,Integer>或任何其他2种类型。

我意识到,我可以让一个类只有2个变量,但这似乎过于啰嗦。

我也意识到我可以使用一个2D数组,但因为我需要使用不同的类型,我必须使他们OBJECT数组,然后我必须一直强制转换。

我只需要在集合中存储对,所以每个条目只需要两个值。像这样的东西不走阶级路线就存在吗?谢谢!


当前回答

在project Reactor (io. projecreactor: Reactor -core)中,有对n-Tuples的高级支持:

Tuple2<String, Integer> t = Tuples.of("string", 1)

在那里你可以得到t.getT1(), t.getT2(),…特别是Stream或Flux,你甚至可以映射元组元素:

Stream<Tuple2<String, Integer>> s;
s.map(t -> t.mapT2(i -> i + 2));

其他回答

对于任何开发Android的人,你都可以使用Android .util. pair。:)

Pair类是那些“给我”泛型示例之一,很容易自己编写。例如,在我的脑海中:

public class Pair<L,R> {

  private final L left;
  private final R right;

  public Pair(L left, R right) {
    assert left != null;
    assert right != null;

    this.left = left;
    this.right = right;
  }

  public L getLeft() { return left; }
  public R getRight() { return right; }

  @Override
  public int hashCode() { return left.hashCode() ^ right.hashCode(); }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Pair)) return false;
    Pair pairo = (Pair) o;
    return this.left.equals(pairo.getLeft()) &&
           this.right.equals(pairo.getRight());
  }

}

是的,它存在于网络上的多个地方,具有不同程度的完整性和特征。(我上面的例子是不可变的。)

我想问你是否不想只使用List<Pair<T, U>>?但是,当然,JDK没有Pair<>类。但我在维基百科和forums.sun.com上都找到了一个。干杯

Java 9 +

在Java 9中,您可以简单地编写:Map。条目(关键字,值) 创建一个不可变的pair。

注意:此方法不允许键或值为空。例如,如果您希望允许空值,则需要将其更改为:Map。条目(关键Optional.ofNullable(值))。


Java 8 +

在Java 8中,您可以使用更通用的javafx.util.Pair来创建不可变的、可序列化的pair。这个类允许空键和空值。(在Java 9中,该类包含在javafx中。基础模块)。编辑:从Java 11开始,JavaFX已经从JDK中解耦了,所以您需要额外的maven构件org.openjfx: JavaFX -base。


Java 6 +

在Java 6及更高版本中,您可以使用更详细的AbstractMap。不可变对或AbstractMap的SimpleImmutableEntry。SimpleEntry的值可以被更改。这些类还允许空键和空值,并且是可序列化的。


安卓

如果你正在为Android编写程序,那就使用Pair。Create (key, value)创建一个不可变的pair。


Apache Commons

Apache Commons Lang提供了有用的Pair。(key, value)来创建不可变的、可比较的、可序列化的对。


Eclipse集合

如果您正在使用包含原语的对,Eclipse Collections提供了一些非常有效的原语对类,可以避免所有低效的自动装箱和自动拆箱。

例如,您可以使用PrimitiveTuples。pair(int, int)来创建一个IntIntPair或PrimitiveTuples。(float, long)来创建一个FloatLongPair。


手卷的实现

从Java 16开始,记录已经脱离预览状态,所以您现在可以执行以下操作:

public record Pair<K, V>(K key, V value) {
    public static <K, V> Pair<K, V> of(K key, V value) {
        return new Pair<>(key, value);
    }
}

上面的实现在未来将有很大的优势,因为它将允许您进行记录解构。

在Java 16之前,您可以使用Project Lombok实现相同的语义:

@Value(staticConstructor = "of")
public class Pair<K, V> {
    K key;
    V value;
}

或者,使用下面的冗长(与已接受的答案中列出的类不同,它可以防止nullpointerexception,并且具有与Records1相同的健壮的hashCode()实现):

import java.util.Objects;

public class Pair<K, V> {

    public final K key;
    public final V value;

    private Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public static <K, V> Pair<K, V> of(K key, V value) {
        return new Pair<>(key, value);
    }

    public boolean equals(Object o) {
        return o instanceof Pair && Objects.equals(key, ((Pair<?,?>)o).key) && Objects.equals(value, ((Pair<?,?>)o).value);
    }

    public int hashCode() {
        return 31 * Objects.hashCode(key) + Objects.hashCode(value);
    }

    public String toString() {
        return key + "=" + value;
    }
}

1在OpenJDK 17上测试

您可以重用现有的Pair或来自“天知道有多少库已经提供了这样的类”的任何此类类。如果你不想从Hans Brende对这个问题的回答中得到任何东西,那么我不认为有任何理由不使用2D数组或对象数组列表/数组列表作为对/元组。你提到了不使用Array的原因:

我也意识到我可以使用一个2D数组,但因为我需要使用不同的类型,我必须使他们OBJECT数组,然后我必须一直强制转换。

即使您使用了来自Accepted Answer的Pair类,您仍然必须强制转换键和值对象。因为你想要存储所有类型的对象。换句话说,List<Pair> pairs与List<Pair<?扩展Object>>对,依次与Object[][2]或List<Object[]>或List<List<Object>>没有区别。因为如果你写下面的代码:

List<Pair> pairs = new ArrayList<>();

// logic for populating pairs into list goes here

// then after sometime you need an element
Pair p = pairs.get(whateverIndex);

Object key = p.getKey(); // We don't know type of key, right?
Object value = p.getValue(); // We don't know the exact type here as well

// All sorts of type guessing statemntes go here
GuessedTypeOfKey finallyMyKey = (GuessedTypeOfKey) key;
GuessedTypeOfValue finallyMyValue = (GuessedTypeOfValue) value;

你仍然需要进行类型转换。所以我找不到任何其他理由不使用2d对象数组或对象数组列表/数组列表作为对/元组。下面是使用List和数组的代码

List<Object[]> simplePairs = new ArrayList<>();

// Add values to pairs
simplePairs.add(new Object[]{1,"One"});
simplePairs.add(new Object[]{"Another Key of Different Type","Value"});
simplePairs.add(new Object[]{"Another Key of Different Type",new AnotherType("Another Value Type")});

// get values
Object[] pair = simplePairs.get(whateverIndex);
Object key = pair[0];
Object value = pair[1];