在Java中返回一对值的最好方法是什么?
这是一个小问题,因为我可以轻松地组成一对class来完成这项工作。 我不想这样做,我觉得应该有一个简单的,内置的,类似于java的方式来返回两个值。 你们是最好的,最简单的方法呢? arrays? 其他一些数据结构?
据我所知,不幸的是没有在Java中的一对内置表示(我当然希望有)。 就个人而言,当我编写一个项目,我发现一个对类通常是有用的,我创build一个通用的Pair<T, U>
类(这可能是你所想的)。 返回一个数组是一种快速而简单的方法,但是稍后你可能会后悔,因为使用你的方法的人会怀疑这个方法是否会返回两个以上的值。
无论你select什么样的解决scheme:当你觉得你需要一个Pair时,你应该考虑使用例如一个通用的Pair类节省的时间是否真的值得信息丢失给下一个阅读代码的人(这个人可能会半年之内你就是你)。 为返回types编写一个单独的类现在需要更多的时间,但它会向那些使用您的方法的用户传递更多的信息(即告诉用户返回值代表什么,并且包含两个值的有用成员名称)。 如果这是一个非公开的方法,只有几个地方使用,但一对更可以接受。
使用容器类是最简单的方法。
public class Pair<T, U> { public final T t; public final U u; public Pair(T t, U u) { this.t= t; this.u= u; } }
我在标准库中看到的最接近的“对”是Map.Entry
接口和实现它的AbstractMap.SimpleEntry
和AbstractMap.SimpleImmutableEntry
类。
如果两个对象是相同的类,则数组更容易使用。
Apache Commons Lang3提供了一个包含ImmutablePair和MutablePair的几个实现的抽象Pair
类。
三种方法,一切都不太好:
- 滚动你自己的
Pair<A, B>
。 你说你不想这样做。 - 返回一个
Object[]
。 这不是types安全的。 - 通过提供单个元素数组作为参数来模拟variables或指针 。
#3的一个例子:
public boolean getUserDetails(String userId, String[] lastName, String[] firstName, Date[] dob) { assert lastName != null && lastName.length == 1; assert firstName != null && firstName.length == 1; assert dob != null && dob.length == 1; ... }
第三个选项使得调用者的生活变得痛苦。
所以就像我说的,没有很好的解决scheme。
顺便说一句,Scala使用各种Tuple类(从我记得的21元组)来帮助你。
有专家告诉我,在面对成对问题时,有两件事是真实的:
- 你需要重新思考你的结构(这个直截了当的答案并不能帮助任何人)
- 你需要build立自己的class级来保持这对
我build议第二种情况并不是那么的不正常。 但是,如果你正在做的事情对于引入一个新class级来说似乎太小了,那么使用一个Map
也可以像其他人所说的那样工作。 如果你只是发回一个单一的回应,然后一个Map
似乎有点多。
如果对的列表听起来像是可以工作的,而且你需要维护顺序,那么你可以尝试一个LinkedHashMap
,以便保持顺序。
我的一些观察:
-
arrays是内置的,快速且易于使用,尽pipe不可能扩大其容量。 如果你想要3个月后返回3个值怎么办?
-
ArrayList /其他收集可以是好的,允许你增加容量(最初10)。 请注意,与ArrayList相比,Vector只能在稍后存储两个值时才能使用。 地图也可以很好,因为它总是被sorting和sorting。
-
一些用户定义的类:如果是有意义的(也就是说返回的数据非常重要,也许是一个Java Bean),那么可能是一个选项,并且你想要存储多于两个的整数。 如果您在其Javadoc中添加更多笔记,则可读性更好。 可以随意扩展,只需在这个类中添加字段。 更慢,但更安全。
JavaFX中有一个类对,但是你不应该使用它。 你应该使用的是这样的:
// We've skipped imports and package declarations public final class YourClass { /* Assume there is a bunch of stuff here */ // I don't know what method you're using, so forgive the silly example public YourClass.Pair sillyExampleOfPairs(String someString) { return new YourClass.Pair(someString, someString.length() * 13); } @Value // Lombok annotation. public static class Pair { String text; int integer; } // this is an even more succinct possibility @Value public static final class ShorterPair {String text; int integer} }
虽然名字Pair在这里显然不是很好的select,你应该select一个更具描述性的名字,这将工作的显而易见的方式(字段是最终的私人,你有一个getter每个,因为注释),不应该是迷失在你身上。 虽然是的,但比使用Pair稍微罗嗦一点,它更健壮。 如果你确实需要为返回值添加一个额外的参数呢? 那么你“只”需要改变这个类。 而且你可以立即更新所有相关的JavaDocs,这也很好。 如果你不得不改变types,那么他们都需要进行类似的工作。
只要你只是添加东西,旧的getText()和getInteger()方法将继续像以前一样工作。 你也避免必须添加另一个依赖项目。 这不是一个很大的胜利。 拥有Pair对于原型来说是很好的,但是对于以后来说这不是很好。
我最后的理论CS-Y论点是Pair是与Pair相同的types。 但是,如果你有一个Phonebook.Entry(带有String和int),并且说,Inventory.Item(带有一个名字和一些我们目前已经被清点的项目),这两个是非常不同的types,它们做的很明显。 你不能把一个人放进去。 这是一件好事。
对于我们这些可怜的混蛋来说,它们也更加清晰,它们必须去掉和debugging你的系统才能在堆栈跟踪中看到类似于“com.name.project.something.something.Phonebook.Entry”的内容,而不是“org.apache.commons.lang3.tuple 。对”。 其中一个告诉我,我应该看什么,并给我一些信息,为什么我看到一对。 另一个说什么都没有。
现在你可能不在乎,你必须input3秒钟才能省3分钟。 但我select相信你内心的善良和你灵魂的高贵。 因此,做正确的事情。
写一个小的静态类来代替。
如果两者都是整数,那么我会build议一个java.awt.Point,否则只需创build一个包含两个对象x和y的容器类