Вопрос-ответ

How to return multiple objects from a Java method?

Как вернуть несколько объектов из метода 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());
}
2023-03-22 00:31 java