Java中的Hashtable将受益于具有元组结构的值。 我可以在Java中使用哪种数据结构来做到这一点?
1
Hashtable
< Long , Tuple
< Set
< Long
> ,Set
< Long
>>> table
= ...
你的意思是一对,即一个长度为2的元组?无论如何,我猜你最好的选择是自己写一堂课,不应该太难。
@Alexander,如果这个特定的Map需要安全的并发访问,那么Hashtable不是正确的选择吗?
我会说用Collections.synchronizedMap(Map)包装会更好。
如果需要并发访问,则ConcurrentHashMap是要使用的正确类。它比同步HashMap或Hashtable更具表现力和更好的性能。
也许我刚刚看到使用HashMap时使用了太多的Hashtables ... Collections.synchronizedMap至少表示你的意图是要同步。虽然是的,ConcurrentHashMap甚至更好。
难道你不能只使用AbstractMap.SimpleEntry ,我之前使用过这个,当我想要实现Pair 之类的行为时,开箱即用。 docs.oracle.com/javase/6/docs/api/java/util/…
这不是要求元组,这是一对或2元组 - 正如@doublep指出的那样。元组应该是n个元素的有序列表,其中n是非负整数。 (另外,元组通常是不可变的。)
你可以编辑标题,以便它是否真的询问对,而不是元组?元组预计是n长度的。答案通常解决配对问题。他们不试图为实际的'元组'提供解决方案,即。一个n元组。因为只需要对来回答这个问题。因此,这个问题的标题与n-tuples的潜在问题重叠。
我不认为Java中有一个通用的元组类,但自定义元组可能就像下面这样简单:
1 2 3 4 5 6 7 8
public class Tuple< X, Y> {
public final X x;
public final Y y;
public Tuple( X x, Y y) {
this .x = x;
this .y = y;
}
}
当然,如何在平等性,不变性等方面进一步设计这个类有一些重要的含义,特别是如果你打算使用实例作为散列的键。
我认为将x 和y 声明为public final 并摆脱那些吸气剂会更好。
那不是一个元组。它只保持对(长度为2的元组)。
我在C#中经常使用元组,如果你想为自己编写一个更大的文件,那么文档非常好:msdn.microsoft.com/de-de/library/vstudio/dd387036.aspx
-1(抱歉)。正如@Anoyz所说,这不是一个元组 - 它是一个2元组或一对。可以使用任意数量的元素创建元组。 - 我猜你的定义可能取决于你来自哪里。
这不起作用。当在Hashtable或HashMap(根据请求)中使用时,它会失败,因为具有相同元素的2个不同元组将提供不同的哈希码。必须覆盖equals() 和hashCode() 。
@YagoMéndezVidal:是的,我的回答的最后一句话说"如果你在平等,不变性等方面进一步设计这个类有一些重要的含义,特别是如果你打算用实例作为散列的关键。"
@ aem999 - 您链接的问题已被删除。
@RustyTheBoyRobot更新了链接stackoverflow.com/questions/3642452/java-n-tuple-implementation
@RustyTheBoyRobot我没有足够的权限来更新评论中的链接 - 链接已更改为:stackoverflow.com/questions/3642452/java-n-tuple-implementation
javatuples是Java中元组的专用项目。
1 2 3
Unit< A> ( 1 element)
Pair< A,B> ( 2 elements)
Triplet< A,B,C> ( 3 elements)
它只覆盖10元组的元组吗?
@ n611x007,我认为每个元组变体都是手写的(即你不能用可变数量的类型参数编写java代码,至少不容易),所以图书馆作者停在某处是有道理的,10似乎像一个合理的数字来支持大多数用例。
javatuple库的一些引人注目的特性如其网站所述 - 所有元组类都是:Typesafe,Immutable,Iterable,Serializable,Comparable(实现Comparable ),实现equals(...)和hashCode(),并实现toString()。知道可能有用。
Apache Commons提供了一些常见的Java实用程序,包括一对。它实现了Map.Entry ,Comparable 和Serializable 。
Apache Commons提供的实现完全符合我的需要。我很高兴有一个有效的实施。
嗯,关于元组的问题似乎是错误的。对!=元组。元组是n长度,即。任何长度。
@naxa请重新检查问题描述,你可能会发现Pair 正是他所需要的。
你是对的,我可能会错误地把我的观点粘贴在一些答案中,包括你的答案。不幸的是,我倾向于根据他们的头衔搜索问题;问题的一部分是不清楚它使用的方式比提问者的实际问题更通用。
@naxa:在泛型类型可以通过参数数量区分的语言中,对于名为Tuple ,Tuple 等的类型来说很好。这些名称在Java中并不好,这不允许这样区分,但是对于具有"真实"泛型类型的语言中具有硬编码类型的类来说,Tuple 不是一个好名称。
Android开发人员注意事项 - Android SDK已经实现了从API 5或API 4(支持库)支持的genric Pair类。
如果您正在寻找内置的Java双元素元组,请尝试AbstractMap.SimpleEntry 。
不太可读。如果我在代码中看到这个,我会想知道地图在哪里。
虽然这个类的目的是为了便于根据javadoc创建自定义地图实现,但这可以很好地完成工作。 +1。此外,在这种情况下,可读性并不是一个大问题。
如果可读性是一个问题,你也可以像这样创建自己的元组:class Tuple extends AbstractMap.SimpleEntry {} 然后你可以将类称为Tuple 。
@yankee如果你经历了创建自己的类的麻烦,为什么要扩展AbstractMap.SimpleEntry ?创建您自己的类型,具有您需要的语义和您的调用者所期望的语义。
@ dimo414:因为SimpleEntry已经实现了equals,hashcode并且拥有其他所需的一切。如果你想要一个通用的Tuple ,那么key 和value 可能是好名字,结果可能已经完全是你需要的了。当然,如果情况并非如此,那么你当然认为自定义实现是一个好主意。
这个类不是一成不变的。可以通过setValue()方法更改值(元组的一个元素)。
作为@maerics很好的答案的扩展,我添加了一些有用的方法:
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 26 27 28 29 30 31 32 33 34 35 36 37 38
public class Tuple
< X, Y
> {
public final X x
;
public final Y y
;
public Tuple
( X x, Y y
) {
this .
x = x
;
this .
y = y
;
}
@Override
public String toString
( ) {
return "(" + x
+ "," + y
+ ")" ;
}
@Override
public boolean equals
( Object other
) {
if ( other
== this ) {
return true ;
}
if ( ! ( other
instanceof Tuple
) ) {
return false ;
}
Tuple
< X,Y
> other_
= ( Tuple
< X,Y
> ) other
;
// this may cause NPE if nulls are valid values for x or y. The logic may be improved to handle nulls properly, if needed.
return other_.
x .
equals ( this .
x ) && other_.
y .
equals ( this .
y ) ;
}
@Override
public int hashCode
( ) {
final int prime
= 31 ;
int result
= 1 ;
result
= prime
* result
+ ( ( x
== null ) ? 0 : x.
hashCode ( ) ) ;
result
= prime
* result
+ ( ( y
== null ) ? 0 : y.
hashCode ( ) ) ;
return result
;
}
}
如果x或y是String,则equals方法将无效。
这是实际的解决方案,因为接受者将在Hashtable 中失败(如问题中所要求的),因为2个相同夫妻的hasCode() 和equals() 将不同。
正如athabaska所指出的那样,只需将Java 7中的equals() 的最后一行替换为return Objects.equals(other_.x == this.x) && Objects.equals(other_.y == this.y) 或使用null检查替换等分的comparson。
@YagoMéndezVidal好点,这是在Eclipse中生成的......
@YagoMéndezVidal,你的意思是Objects.equals(other.x, this.x) 等?该方法接受两个Object引用作为参数,而不是布尔值。
是的,当然,@ VictorZamanian,你是对的。
另外2美分:从Java 7开始,现在标准Lib中有一个类:javafx.util.Pair。
是的,它是标准的Java,现在JavaFx包含在JDK中:)
3元组怎么样?
一个值为一对的配对应该可以做到,不是吗?
这是一个丑陋的黑客。那么你是否会成对配对一对4元组?
我认为如果你需要一个4元组,那么开始考虑使用表格或者你自己的classe是一件好事...
Aaaand将在JDK 9中使用拼图。我的意思是你仍然可以使用它,但是你真的想将javafx包含在你的项目中吗?因为这个类? :)
在这里,我仍然希望javafx(Properties,Pair等)的"实用程序"部分将迁移到java的核心,或者至少迁移到特定的模块
可悲的是,javafx将很快再次从JRE中删除。
这是其他地方的完全相同的问题,其中包括一个更强大的equals ,hash ,其中maerics暗示:
http://groups.google.com/group/comp.lang.java.help/browse_thread/thread/f8b63fc645c1b487/1d94be050cfc249b
那个讨论继续反映了maerics和ColinD的方法"我应该重新使用一个具有非特定名称的类元组,或者在每次遇到这种情况时创建一个具有特定名称的新类"。多年前我在后一个营地;我已经发展成为支持前者。
你可以在关闭组或其他任何组合之前粘贴相关部分吗?因此,我们鼓励将相关信息复制到现场。
如果一个方法应该检查double[] 并计算最小值,最大值,平均值和标准差,那么将它存储到传入的double[4] 中可能不如使用带有命名字段的类型那么优雅但是,想知道发生了什么的人只需要阅读该方法的文档,而不必阅读自定义返回类型的文档(或直接检查它的代码)。能够返回匿名值类型会更好,但Java不支持这样的东西。实际上,如果我控制了Java ......
...我将一些字段添加到名为tempLong1 ,tempLong2 ,tempObject1 ,TempObject2 等的Thread 中,以最大限度地减少需要创建的临时对象的数量,仅用于能够从方法返回多个东西。 Icky,但没有其他清洁解决方案。
使用lombok,很容易声明一个Pair 类:
1 2 3 4 5
@Data( staticConstructor = "of" )
public class Pair< A, B> {
private final A left;
private final B right;
}
这将生成名为"of",equals() ,hashcode() 和toString() 的getter,静态构造函数。
有关更多信息,请参阅@Data 文档
如果两个字段A和B是最终的,那么Iombok如何做到这一点?
检查github上的消息来源,我个人不知道内部。 final 这里确保我们得到一个带有"左"和"右"参数且没有setter的静态构造函数
@LucasCrawford字段是final ,但类不是。您需要可扩展的类来执行代理等操作。此外,当考虑反射时,final s仅承载如此多的重量(参见Class.setAccessible(boolean) )。
Android Tuple Utils
此对象提供equals()的合理实现,如果equals()在每个包含的对象上为true,则返回true。
创建一个类,描述您实际建模和使用它的概念。它可以只存储两个Set 并为它们提供访问器,但是它应该被命名以指示每个集合究竟是什么以及为什么它们被组合在一起。
啊,问题是错的。这些是有序的?可以有重复的元素吗?元组怎么样? ;)
值得一提的是Auto / Value - 它可以让您创建自己的类型安全无痛。它可以说比使用泛型Pair 或Tuple 类型更容易。
为了补充@ maerics的答案,这里是Comparable 元组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
import java.util.* ;
/**
* A tuple of two classes that implement Comparable
*/
public class ComparableTuple< X extends Comparable<? super X> , Y extends Comparable<? super Y>>
extends Tuple< X, Y>
implements Comparable< ComparableTuple< X, Y>>
{
public ComparableTuple( X x, Y y) {
super ( x, y) ;
}
/**
* Implements lexicographic order
*/
public int compareTo( ComparableTuple< X, Y> other) {
int d = this .x .compareTo ( other.x ) ;
if ( d == 0 )
return this .y .compareTo ( other.y ) ;
return d;
}
}
这也是因为元组应该是Pairs这个问题的错误假设......元组有任何长度,而不仅仅是2。
@naxa比什么都没有好。此外,您可以嵌套对。
@AlexeiAverchenko,是一组4对Tuple-5,总........
虽然这篇文章已经很老了,虽然我知道我不是很有帮助,但我认为这里完成的工作是:http://www.pds.ewi.tudelft.nl/pubs/papers/cpe2005.pdf,在主流Java方面会很好。
你可以这样做:
1 2 3 4
int a;
char b;
float c;
[ a,b,c] = [ 3 ,'a' ,2.33 ] ;
要么
1
[ int ,int ,char ] x = [ 1 ,2 ,'a' ] ;
要么
1 2 3 4 5 6 7
public [ int ,boolean ] Find( int i)
{
int idx = FindInArray( A,i) ;
return [ idx,idx>= 0 ] ;
}
[ idx, found] = Find( 7 ) ;
这里的元组是:
定义为基本类型 - 没有模板/泛型
堆栈分配,如果在本地声明
使用模式匹配进行分配
这种方法增加了
是否有任何尝试将其实际纳入标准Java?或者一些项目进一步采取了这几步?
上面的文章确实引用了一个实现元组的专有Java编译器。我不认为它在标准Java中被考虑过。
在2001年到2008年的几篇研究论文中,我发现了一些对这个扩展的引用(似乎是Spar / Java)。如果有人还在研究它(或者为什么不删除它),那将会很有趣。
围绕此Java社区中有一些活动。例如,请参阅:blogs.oracle.com/jrose/entry/tuples_in_the_vm
我将从关于Java中元组的一般观点开始,并以对您具体问题的含义完成。
1)在Java中避免使用非通用语言中的元组的方式,因为它们不是类型安全的(例如在Python中:tuple = (4, 7.9, 'python') )。如果您仍想使用通用元组(不推荐使用)之类的东西,则应使用Object[] 或List 并在检查后使用instanceof 转换元素以确保类型安全。
通常,某个设置中的元组总是以相同的方式使用,包含相同的结构。在Java中,您必须在class 中显式定义此结构,以提供定义良好的类型安全值和方法。这看起来很烦人且不必要,但在编译时已经防止了错误。
2)如果需要包含相同(超级)类Foo 的元组,请使用Foo[] ,List 或List extends Foo> (或列表的不可变对应项)。由于元组不是定义的长度,因此该解决方案是等效的。
3)在你的情况下,你似乎需要一个Pair (即一个定义明确的长度为2的元组)。这使得maerics的答案或其中一个补充答案最有效,因为您可以在将来重用代码。
元组不安全吗?那是bs。以C ++元组为例(更不用说Haskell,Scala等)。如果容器可以存储不同类型的值,并不意味着它不是类型安全的。如果有的话,Java的限制会阻止实现正确的元组。
@DanM。你是对的。我相应地编辑了我的回答,只是明确地引用了非通用语言。请考虑以礼貌的方式表达您的意见。
您可以使用Google Guava Table