Как вернуть несколько объектов из метода Java?
Я хочу вернуть два объекта из метода Java, и мне было интересно, какой может быть хороший способ сделать это?
Возможные способы, о которых я могу подумать, следующие: вернуть HashMap
(поскольку два объекта связаны) или вернуть ArrayList
из Object
объектов.
Чтобы быть более точным, два объекта, которые я хочу вернуть, - это (a) List
объектов и (b) одинаковые имена, разделенные запятыми.
Я хочу вернуть эти два объекта из одного метода, потому что я не хочу перебирать список объектов, чтобы получить имена, разделенные запятыми (что я могу сделать в том же цикле в этом методе).
Почему-то возврат a HashMap
выглядит не очень элегантным способом сделать это.
Переведено автоматически
Ответ 1
Если вы хотите вернуть два объекта, вы обычно хотите вернуть один объект, который инкапсулирует эти два объекта.
Вы могли бы вернуть список NamedObject
объектов, подобных этому:
public class NamedObject<T> {
public final String name;
public final T object;
public NamedObject(String name, T object) {
this.name = name;
this.object = object;
}
}
Тогда вы можете легко вернуть List<NamedObject<WhateverTypeYouWant>>
.
Также: почему вы хотите возвращать список имен, разделенных запятыми, вместо List<String>
? Или, еще лучше, верните a Map<String,TheObjectType>
с ключами, представляющими собой имена и значения объектов (если только ваши объекты не имеют указанного порядка, и в этом случае a NavigableMap
может быть тем, что вы хотите.
Ответ 2
Если вы знаете, что собираетесь вернуть два объекта, вы также можете использовать общую пару:
public class Pair<A,B> {
public final A a;
public final B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
};
Отредактируйте более полно сформированную реализацию вышеизложенного:
package util;
public class Pair<A,B> {
public static <P, Q> Pair<P, Q> makePair(P p, Q q) {
return new Pair<P, Q>(p, q);
}
public final A a;
public final B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((b == null) ? 0 : b.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
@SuppressWarnings("rawtypes")
Pair other = (Pair) obj;
if (a == null) {
if (other.a != null) {
return false;
}
} else if (!a.equals(other.a)) {
return false;
}
if (b == null) {
if (other.b != null) {
return false;
}
} else if (!b.equals(other.b)) {
return false;
}
return true;
}
public boolean isInstance(Class<?> classA, Class<?> classB) {
return classA.isInstance(a) && classB.isInstance(b);
}
@SuppressWarnings("unchecked")
public static <P, Q> Pair<P, Q> cast(Pair<?, ?> pair, Class<P> pClass, Class<Q> qClass) {
if (pair.isInstance(pClass, qClass)) {
return (Pair<P, Q>) pair;
}
throw new ClassCastException();
}
}
Примечания, в основном касающиеся проблем с Java и generics:
- оба
a
иb
являются неизменяемыми. makePair
статический метод помогает вам с набором текста, который оператор diamond в Java 7 сделает менее раздражающим. Есть некоторая работа, чтобы сделать этот re: generics действительно приятным, но теперь все должно быть в порядке. (c.f. PECS)hashcode
иequals
генерируются eclipse.- приведение во время компиляции в
cast
методе в порядке, но кажется не совсем правильным. - Я не уверен, нужны ли подстановочные знаки в
isInstance
. - Я только что написал это в ответ на комментарии, только для иллюстрации.
Ответ 3
В случае, если вызываемый вами метод является частным или вызывается из одного места, попробуйте
return new Object[]{value1, value2};
Вызывающий объект выглядит следующим образом:
Object[] temp=myMethod(parameters);
Type1 value1=(Type1)temp[0]; //For code clarity: temp[0] is not descriptive
Type2 value2=(Type2)temp[1];
Пример пары Дэвида Ханака не имеет синтаксических преимуществ и ограничен двумя значениями.
return new Pair<Type1,Type2>(value1, value2);
И вызывающий объект выглядит следующим образом:
Pair<Type1, Type2> temp=myMethod(parameters);
Type1 value1=temp.a; //For code clarity: temp.a is not descriptive
Type2 value2=temp.b;
Ответ 4
Вы можете использовать любой из следующих способов:
private static final int RETURN_COUNT = 2;
private static final int VALUE_A = 0;
private static final int VALUE_B = 1;
private static final String A = "a";
private static final String B = "b";
1) Используя массив
private static String[] methodWithArrayResult() {
//...
return new String[]{"valueA", "valueB"};
}
private static void usingArrayResultTest() {
String[] result = methodWithArrayResult();
System.out.println();
System.out.println("A = " + result[VALUE_A]);
System.out.println("B = " + result[VALUE_B]);
}
2) Используя ArrayList
private static List<String> methodWithListResult() {
//...
return Arrays.asList("valueA", "valueB");
}
private static void usingListResultTest() {
List<String> result = methodWithListResult();
System.out.println();
System.out.println("A = " + result.get(VALUE_A));
System.out.println("B = " + result.get(VALUE_B));
}
3) Используя HashMap
private static Map<String, String> methodWithMapResult() {
Map<String, String> result = new HashMap<>(RETURN_COUNT);
result.put(A, "valueA");
result.put(B, "valueB");
//...
return result;
}
private static void usingMapResultTest() {
Map<String, String> result = methodWithMapResult();
System.out.println();
System.out.println("A = " + result.get(A));
System.out.println("B = " + result.get(B));
}
4) Используя ваш пользовательский класс контейнера
private static class MyContainer<M,N> {
private final M first;
private final N second;
public MyContainer(M first, N second) {
this.first = first;
this.second = second;
}
public M getFirst() {
return first;
}
public N getSecond() {
return second;
}
// + hashcode, equals, toString if need
}
private static MyContainer<String, String> methodWithContainerResult() {
//...
return new MyContainer("valueA", "valueB");
}
private static void usingContainerResultTest() {
MyContainer<String, String> result = methodWithContainerResult();
System.out.println();
System.out.println("A = " + result.getFirst());
System.out.println("B = " + result.getSecond());
}
5) Используя AbstractMap.simpleEntry
private static AbstractMap.SimpleEntry<String, String> methodWithAbstractMapSimpleEntryResult() {
//...
return new AbstractMap.SimpleEntry<>("valueA", "valueB");
}
private static void usingAbstractMapSimpleResultTest() {
AbstractMap.SimpleEntry<String, String> result = methodWithAbstractMapSimpleEntryResult();
System.out.println();
System.out.println("A = " + result.getKey());
System.out.println("B = " + result.getValue());
}
6) Используя пару из Apache Commons
private static Pair<String, String> methodWithPairResult() {
//...
return new ImmutablePair<>("valueA", "valueB");
}
private static void usingPairResultTest() {
Pair<String, String> result = methodWithPairResult();
System.out.println();
System.out.println("A = " + result.getKey());
System.out.println("B = " + result.getValue());
}