Dav*_*nds 655 java tuples std-pair
有没有一个很好的理由为什么Pair<L,R>Java中没有?这个C++构造的等价物是什么?我宁愿避免重新实现自己.
似乎1.6提供类似的东西(AbstractMap.SimpleEntry<K,V>),但这看起来很复杂.
Luc*_*lle 392
在一个线程中comp.lang.java.help,Hunter Gratzner提出了一些反对PairJava中构造的存在的论据.主要论点是一个类Pair没有传达关于两个值之间关系的任何语义(你怎么知道"第一"和"第二"是什么意思?).
更好的做法是为每个应用程序编写一个非常简单的类,就像Mike提出的Pair类一样.Map.Entry是一个在其名称中带有其含义的对的示例.
总而言之,在我看来,最好有一个类Position(x,y),一个类Range(begin,end)和一个类,Entry(key,value)而不是一个通用的Pair(first,second),它不会告诉我它应该做什么.
And*_*rey 150
这是Java.您必须使用描述性类和字段名称来创建自己的定制Pair类,并且不要介意通过编写hashCode()/ equals()或一次又一次地实现Comparable来重新发明轮子.
art*_*urh 102
HashMap兼容Pair类:
public class Pair<A, B> {
private A first;
private B second;
public Pair(A first, B second) {
super();
this.first = first;
this.second = second;
}
public int hashCode() {
int hashFirst = first != null ? first.hashCode() : 0;
int hashSecond = second != null ? second.hashCode() : 0;
return (hashFirst + hashSecond) * hashSecond + hashFirst;
}
public boolean equals(Object other) {
if (other instanceof Pair) {
Pair otherPair = (Pair) other;
return
(( this.first == otherPair.first ||
( this.first != null && otherPair.first != null &&
this.first.equals(otherPair.first))) &&
( this.second == otherPair.second ||
( this.second != null && otherPair.second != null &&
this.second.equals(otherPair.second))) );
}
return false;
}
public String toString()
{
return "(" + first + ", " + second + ")";
}
public A getFirst() {
return first;
}
public void setFirst(A first) {
this.first = first;
}
public B getSecond() {
return second;
}
public void setSecond(B second) {
this.second = second;
}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*fel 53
使用Lombok,我能想到的最短的一对是:
@Data
@AllArgsConstructor(staticName = "of")
public class Pair<F, S> {
private F first;
private S second;
}
Run Code Online (Sandbox Code Playgroud)
它具有的所有优点的答案从@arturh(可比性除外),它有hashCode,equals,toString和静态的"构造".
Mat*_*nos 35
Apache Commons Lang 3.0+有几个Pair类:http: //commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/package-summary.html
Pet*_*rey 31
另一种实现Pair的方法.
简单的工厂,所以你不必提供类型.例如Pair.of("你好",1);
public class Pair<FIRST, SECOND> implements Comparable<Pair<FIRST, SECOND>> {
public final FIRST first;
public final SECOND second;
private Pair(FIRST first, SECOND second) {
this.first = first;
this.second = second;
}
public static <FIRST, SECOND> Pair<FIRST, SECOND> of(FIRST first,
SECOND second) {
return new Pair<FIRST, SECOND>(first, second);
}
@Override
public int compareTo(Pair<FIRST, SECOND> o) {
int cmp = compare(first, o.first);
return cmp == 0 ? compare(second, o.second) : cmp;
}
// todo move this to a helper class.
private static int compare(Object o1, Object o2) {
return o1 == null ? o2 == null ? 0 : -1 : o2 == null ? +1
: ((Comparable) o1).compareTo(o2);
}
@Override
public int hashCode() {
return 31 * hashcode(first) + hashcode(second);
}
// todo move this to a helper class.
private static int hashcode(Object o) {
return o == null ? 0 : o.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
if (this == obj)
return true;
return equal(first, ((Pair) obj).first)
&& equal(second, ((Pair) obj).second);
}
// todo move this to a helper class.
private boolean equal(Object o1, Object o2) {
return o1 == null ? o2 == null : (o1 == o2 || o1.equals(o2));
}
@Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
Run Code Online (Sandbox Code Playgroud)cyb*_*ion 27
http://www.javatuples.org/index.html怎么样我发现它非常有用.
javatuples为您提供从1到10个元素的元组类:
Unit<A> (1 element)
Pair<A,B> (2 elements)
Triplet<A,B,C> (3 elements)
Quartet<A,B,C,D> (4 elements)
Quintet<A,B,C,D,E> (5 elements)
Sextet<A,B,C,D,E,F> (6 elements)
Septet<A,B,C,D,E,F,G> (7 elements)
Octet<A,B,C,D,E,F,G,H> (8 elements)
Ennead<A,B,C,D,E,F,G,H,I> (9 elements)
Decade<A,B,C,D,E,F,G,H,I,J> (10 elements)
Run Code Online (Sandbox Code Playgroud)
cle*_*tus 12
这取决于你想用它做什么.这样做的典型原因是迭代地图,您只需执行此操作(Java 5+):
Map<String, Object> map = ... ; // just an example
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.printf("%s -> %s\n", entry.getKey(), entry.getValue());
}
Run Code Online (Sandbox Code Playgroud)
she*_*pya 12
android提供了Pair类(http://developer.android.com/reference/android/util/Pair.html),这里的实现:
public class Pair<F, S> {
public final F first;
public final S second;
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Pair)) {
return false;
}
Pair<?, ?> p = (Pair<?, ?>) o;
return Objects.equal(p.first, first) && Objects.equal(p.second, second);
}
@Override
public int hashCode() {
return (first == null ? 0 : first.hashCode()) ^ (second == null ? 0 : second.hashCode());
}
public static <A, B> Pair <A, B> create(A a, B b) {
return new Pair<A, B>(a, b);
}
}
Run Code Online (Sandbox Code Playgroud)
最大的问题可能是无法确保A和B的不变性(请参阅如何确保类型参数是不可变的)因此hashCode()可能会在插入集合之后为同一对提供不一致的结果(这会产生未定义的行为) ,请参阅根据可变字段定义等于).对于特定(非泛型)Pair类,程序员可以通过仔细选择A和B为不可变来确保不变性.
无论如何,从@ PeterLawrey的答案中清除泛型的警告(java 1.7):
public class Pair<A extends Comparable<? super A>,
B extends Comparable<? super B>>
implements Comparable<Pair<A, B>> {
public final A first;
public final B second;
private Pair(A first, B second) {
this.first = first;
this.second = second;
}
public static <A extends Comparable<? super A>,
B extends Comparable<? super B>>
Pair<A, B> of(A first, B second) {
return new Pair<A, B>(first, second);
}
@Override
public int compareTo(Pair<A, B> o) {
int cmp = o == null ? 1 : (this.first).compareTo(o.first);
return cmp == 0 ? (this.second).compareTo(o.second) : cmp;
}
@Override
public int hashCode() {
return 31 * hashcode(first) + hashcode(second);
}
// TODO : move this to a helper class.
private static int hashcode(Object o) {
return o == null ? 0 : o.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
if (this == obj)
return true;
return equal(first, ((Pair<?, ?>) obj).first)
&& equal(second, ((Pair<?, ?>) obj).second);
}
// TODO : move this to a helper class.
private boolean equal(Object o1, Object o2) {
return o1 == o2 || (o1 != null && o1.equals(o2));
}
@Override
public String toString() {
return "(" + first + ", " + second + ')';
}
}
Run Code Online (Sandbox Code Playgroud)
非常欢迎添加/更正:)特别是我对我的使用不太确定Pair<?, ?>.
有关此语法原因的详细信息,请参阅确保对象实现Comparable以及详细说明如何max(Comparable a, Comparable b)在Java中实现泛型函数?
好消息JavaFX具有关键价值。
只需将javafx添加为依赖项并导入javafx.util.Pair;
并像中那样简单地使用c++。
Pair <Key, Value>
Run Code Online (Sandbox Code Playgroud)
例如
Pair <Integer, Integer> pr = new Pair<Integer, Integer>()
pr.get(key);// will return corresponding value
Run Code Online (Sandbox Code Playgroud)
小智 5
在我看来,Java中没有Pair,因为如果你想直接在对上添加额外的功能(例如Comparable),你必须绑定类型.在C++中,我们只是不关心,如果组成一对的类型没有operator <,那么pair::operator <也不会编译.
没有边界的可比较的示例:
public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static int compare(Object l, Object r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : ((Comparable) (l)).compareTo(r);
}
}
}
/* ... */
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
//Runtime error here instead of compile error!
System.out.println(a.compareTo(b));
Run Code Online (Sandbox Code Playgroud)
Comparable与编译时检查的示例是否类型参数具有可比性:
public class Pair<
F extends Comparable<? super F>,
S extends Comparable<? super S>
> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static <
T extends Comparable<? super T>
> int compare(T l, T r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : l.compareTo(r);
}
}
}
/* ... */
//Will not compile because Thread is not Comparable<? super Thread>
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
System.out.println(a.compareTo(b));
Run Code Online (Sandbox Code Playgroud)
这很好,但是这次你可能不会在Pair中使用非可比类型作为类型参数.在某些实用程序类中,可能会使用大量的Comparators for Pair,但C++人员可能无法获得它.另一种方法是在类型层次结构中编写许多类,在类型参数上使用不同的边界,但是有太多可能的边界及其组合......
正如许多其他人已经说过的那样,如果Pair类是否有用,它实际上取决于用例.
我认为对于私有帮助函数来说,使用Pair类是完全合法的,如果这样可以使代码更具可读性,并且不值得创建具有所有样板代码的另一个值类.
另一方面,如果您的抽象级别要求您清楚地记录包含两个对象或值的类的语义,那么您应该为它编写一个类.通常情况下,如果数据是业务对象.
一如既往,它需要熟练的判断.
对于第二个问题,我建议使用Apache Commons库中的Pair类.那些可能被视为Java的扩展标准库:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
您可能还想看看Apache Commons的EqualsBuilder,HashCodeBuilder和ToStringBuilder,它们简化了为业务对象编写值类的过程.
根据 Java 语言的性质,我想人们实际上并不需要Pair,通常他们需要的是接口。下面是一个例子:
interface Pair<L, R> {
public L getL();
public R getR();
}
Run Code Online (Sandbox Code Playgroud)
因此,当人们想要返回两个值时,他们可以执行以下操作:
... //Calcuate the return value
final Integer v1 = result1;
final String v2 = result2;
return new Pair<Integer, String>(){
Integer getL(){ return v1; }
String getR(){ return v2; }
}
Run Code Online (Sandbox Code Playgroud)
这是一个非常轻量级的解决方案,它回答了“a 的语义是Pair<L,R>什么?”的问题。答案是,这是一个具有两种(可能不同)类型的接口构建,并且它具有返回每种类型的方法。您可以为其添加进一步的语义。例如,如果您正在使用 Position 并且真的想在您的代码中指明它,您可以定义PositionX和PositionY包含Integer, 来组成一个Pair<PositionX,PositionY>. 如果 JSR 308 可用,您也可以使用它Pair<@PositionX Integer, @PositionY Ingeger>来简化它。
编辑:我应该在这里指出的一件事是上面的定义明确地关联了类型参数名称和方法名称。这是对那些认为 aPair缺乏语义信息的人的回答。实际上,该方法的getL意思是“给我与类型参数L的类型相对应的元素”,这确实意味着什么。
编辑:这是一个简单的实用程序类,可以使生活更轻松:
class Pairs {
static <L,R> Pair<L,R> makePair(final L l, final R r){
return new Pair<L,R>(){
public L getL() { return l; }
public R getR() { return r; }
};
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
return Pairs.makePair(new Integer(100), "123");
Run Code Online (Sandbox Code Playgroud)
小智 5
Map.Entry接口非常接近 C++ 对。看具体的实现,比如AbstractMap.SimpleEntry和 AbstractMap.SimpleImmutableEntry 第一项是 getKey() 第二项是 getValue()。
| 归档时间: |
|
| 查看次数: |
446586 次 |
| 最近记录: |