A Java collection of value pairs? (tuples?)
我喜欢Java有一个地图,你可以在地图中定义每个条目的类型,例如EDCOX1×0。
我要查找的是一种集合类型,其中集合中的每个元素都是一对值。对中的每个值都可以有自己的类型(如上面的字符串和整数示例),这是在声明时定义的。
集合将保持其给定的顺序,并且不会将其中一个值视为唯一键(如在映射中)。
本质上,我希望能够定义一个类型为
我意识到我可以创建一个只包含两个变量的类,但这似乎过于冗长。
我也意识到我可以使用二维数组,但是由于我需要使用的类型不同,我必须使它们成为对象数组,然后我必须一直进行强制转换。
我只需要在集合中存储对,所以每个条目只需要两个值。像这样的东西不走上课路线就存在吗?谢谢!
抽象地图.simpleEntry
很简单,您正在寻找:
你怎么填?
1 2 3 4 | java.util.Map.Entry<String,Integer> pair1=new java.util.AbstractMap.SimpleEntry<>("Not Unique key1",1); java.util.Map.Entry<String,Integer> pair2=new java.util.AbstractMap.SimpleEntry<>("Not Unique key2",2); pairList.add(pair1); pairList.add(pair2); |
这简化为:
1 2 3 4 |
并且,借助于
1 2 | pairList.add(createEntry("Not Unique key1", 1)); pairList.add(createEntry("Not Unique key2", 2)); |
由于
1 2 3 |
pair类是那些"gimme"泛型示例之一,这些示例很容易自己编写。例如,在我的头顶上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Pair<L,R> { private final L left; private final R right; public Pair(L left, R right) { 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()); } } |
是的,这存在于网络上的多个地方,具有不同程度的完整性和特性。(我上面的例子是不可变的。)
Java 9 +
在Java 9中,可以简单地编写:EDCOX1,0,创建不可变对。
注意:此方法不允许键或值为空。例如,如果您想允许空值,您可以将其更改为:
在Java 8中,可以使用更通用的EDCOX1(2)来创建一个不可变的、可串行化的对。此类不允许空键和空值。(在Java 9中,这个类包含在EDCOX1 3)模块中。编辑:对于Java 11,JavaFX已经与JDK脱钩,因此您需要额外的Maven工件org .OpenJFX:JavaFX Basic。
Java 6 +在Java 6和UP中,对于一个值可以改变的对,可以使用更冗长的EDCOX1(4)对不可变的一对,或者EDCOX1×5Ω。这些类还允许空键和空值,并且是可序列化的。
安卓如果您是为Android编写,只需使用
如果您使用的是包含原语的对,那么Eclipse集合将提供一些非常有效的原语对类,以避免所有效率低下的自动装箱和自动拆箱。
例如,可以使用
使用Project Lombok,只需编写以下内容,就可以创建不可变的对类:
1 2 3 4 5 | @Value public class Pair<K, V> { K key; V value; } |
Lombok将在生成的字节码中自动为您填写constructor、getters、
如果上面的所有解决方案都没有使您的船浮起,您可以简单地复制和粘贴以下代码(与接受的答案中列出的类不同,这可以防止nullpointerExceptions):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import java.util.Objects; public class Pair<K, V> { public final K key; public final V value; public Pair(K key, V value) { this.key = key; this.value = 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; } } |
这些内置类也是一个选项。两者都实现了
AbstractMap.SimpleEntry AbstractMap.SimpleImmutableEntry
APACHE通用Lang3有两个类,在这个线程中提到的其他几个库,与Java中的C++对l、R>等价的是什么?
符合原始问题要求的示例:
1 2 3 4 5 6 7 8 9 10 11 | List<Pair<String, Integer>> myPairs = new ArrayList<Pair<String, Integer>>(); myPairs.add(Pair.of("val1", 11)); myPairs.add(Pair.of("val2", 17)); //... for(Pair<String, Integer> pair : myPairs) { //following two lines are equivalent... whichever is easier for you... System.out.println(pair.getLeft() +":" + pair.getRight()); System.out.println(pair.getKey() +":" + pair.getValue()); } |
对于任何为Android开发的人,您都可以使用android.util.pair。:)
"ApacheCommonsLang3"的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; ... @SuppressWarnings("unchecked") Pair<String, Integer>[] arr = new ImmutablePair[]{ ImmutablePair.of("A", 1), ImmutablePair.of("B", 2)}; // both access the 'left' part String key = arr[0].getKey(); String left = arr[0].getLeft(); // both access the 'right' part Integer value = arr[0].getValue(); Integer right = arr[0].getRight(); |
1 2 3 4 5 | <dependency> <groupId>org.apache.commons</groupId> commons-lang3</artifactId> <version>3.4</version> </dependency> |
您可以编写一个泛型对类,并在数组或列表中使用它。是的,您必须编写一个类,但是您可以为所有类型重用同一个类,因此您只需要编写一次。
我想问你是不是不想只用一个
如您所描述的,首选的解决方案是一组对(即列表)。
为了实现这一点,您将创建一个在集合中使用的Pair类。这是一个有用的实用程序类,可以添加到代码库中。
SunJDK中最接近的类,提供类似于典型的Pair类的功能,是AbstractMap.SimpleEntry。你可以使用这个类,而不是创建你自己的配对类,尽管你必须忍受一些尴尬的限制,我认为大多数人会对这一点表示不满,因为它不是SimpleEntry的预期角色。例如,simpleEntry没有"setkey()"方法,也没有默认的构造函数,因此您可能会发现它太有限。
请记住,集合的设计目的是包含单个类型的元素。相关的实用程序接口(如map)实际上不是集合(即map不实现集合接口)。一对组合也不会实现收集接口,但在构建更大的数据结构中显然是一个有用的类。
扩展其他答案时,一般不可变对应该具有静态方法,以避免将代码与对构造函数的调用混淆在一起:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Pair<L,R> { final L left; final R right; public Pair(L left, R right) { this.left = left; this.right = right; } static <L,R> Pair<L,R> of(L left, R right){ return new Pair<L,R>(left, right); } } |
如果您将静态方法命名为"of"或"pairof",那么代码将变得流畅,因为您可以编写:
1 2 | list.add(Pair.of(x,y)); // my preference list.add(pairOf(x,y)); // use with import static x.y.Pair.pairOf |
这是一个真正的耻辱,核心Java库是如此稀少,这样的事情,你必须使用共用的朗朗或其他第三方来做这样的基本东西。还有另一个升级到scala的原因…
这是基于javahelp4u的代码。
不那么冗长,并且显示如何在一行中进行操作以及如何循环操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | //======> Imports import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; //======> Single Entry SimpleEntry<String, String> myEntry = new SimpleEntry<String, String>("ID","Text"); System.out.println("key:" + myEntry.getKey() +" value:" + myEntry.getValue()); System.out.println(); //======> List of Entries List<Entry<String,String>> pairList = new ArrayList<>(); //-- Specify manually Entry<String,String> firstButton = new SimpleEntry<String, String>("Red","Way out"); pairList.add(firstButton); //-- one liner: pairList.add(new SimpleEntry<String,String>("Gray","Alternate route")); //Ananomous add. //-- Iterate over Entry array: for (Entry<String, String> entr : pairList) { System.out.println("Button:" + entr.getKey() +" Label:" + entr.getValue()); } |
创建一个类
1 2 3 4 5 | class tuples { int x; int y; } |
然后创建这个元组对象的列表
1 | List<tuples> list = new ArrayList<tuples>(); |
因此,您也可以用相同的方式实现其他新的数据结构。
ApacheCrunch还有一个
我的意思是,即使Java中没有EDCOX1的18个类,也有相当的SimMalar:EDCOX1,21
地图录入文件
这(简化了很多)是
您可以创建一个EDOCX1的实例(23),将您的值存储在其中并获取条目集。你最终会得到一个
所以:
1 2 3 4 5 6 7 8 |
在项目反应器(IO.项目反应器:反应器芯)中,有对n-tuples的高级支持:
1 |
在这里,您可以得到
1 2 |
那com.sun.tools.javac.util.pair呢?
在谈到键/值对时,我首先想到的是属性类,在该类中,可以将项保存并加载到流/文件中。