Java 메소드에서 두 개의 객체를 반환하고 좋은 방법이 무엇인지 궁금합니다.
내가 생각할 수있는 가능한 방법은 a를 반환하거나 HashMap
(두 개의 객체가 관련되어 있기 때문에) 객체를 반환하는 것 ArrayList
입니다 Object
.
더 정확하게 말하면 반환하려는 두 객체는 (a) List
객체와 (b) 동일한 이름의 쉼표로 구분 된 이름입니다.
객체 목록을 반복하여 쉼표로 구분 된 이름을 얻지 않기 때문에이 두 객체를 반환하고 싶습니다 (이 방법에서 동일한 루프에서 수행 할 수 있음).
어쨌든, a를 반환한다고 HashMap
해서 매우 우아한 방법은 아닙니다.
답변
두 객체를 반환하려면 일반적으로 두 객체를 캡슐화하는 단일 객체를 반환하려고합니다.
다음 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>
? 또는 더 나은 방법으로 Map<String,TheObjectType>
키가 객체의 이름과 값인 객체를 반환 하십시오 (객체가 순서를 지정하지 않은 경우 a NavigableMap
가 원하는 것일 수 있습니다).
답변
두 개의 객체를 반환한다는 것을 알고 있다면 일반 쌍을 사용할 수도 있습니다.
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 및 제네릭을 사용한 녹 슬림에 대한 참고 사항 :
- 모두
a
와b
불변입니다. makePair
정적 방법은 보일러 플레이트 타이핑에 도움이되며 Java 7의 다이아몬드 연산자는 덜 성가 시게합니다. 이것을 정말 멋지게 만드는 작업이 있습니다 : 제네릭이지만 지금은 괜찮을 것입니다. (cf PECS)hashcode
과equals
식에 의해 생성된다.- 컴파일 타임 캐스팅
cast
메소드 는 괜찮지 만, 옳지 않은 것 같습니다. - 와일드 카드가 있는지 확실하지 않습니다.
isInstance
가 필요한지 . - 나는 단지 설명 목적으로 주석에 대한 응답으로 이것을 작성했습니다.
답변
호출하는 메소드가 비공개이거나 한 위치에서 호출 된 경우 시도하십시오
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];
David Hanak의 Pair 예제는 구문상의 이점이 없으며 두 가지 값으로 제한됩니다.
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;
답변
다음 방법 중 하나를 사용할 수 있습니다.
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) 사용 쌍 의 아파치 코 몬즈을
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());
}
답변
Java로 코딩 할 때 거의 항상 n-Tuple 클래스를 정의하게됩니다. 예를 들어 :
public class Tuple2<T1,T2> {
private T1 f1;
private T2 f2;
public Tuple2(T1 f1, T2 f2) {
this.f1 = f1; this.f2 = f2;
}
public T1 getF1() {return f1;}
public T2 getF2() {return f2;}
}
나는 그것이 추악하다는 것을 알고 있지만 효과가 있으며 튜플 유형을 한 번만 정의하면됩니다. 튜플은 Java에 실제로 부족한 것입니다.
편집 : David Hanak의 예는 게터 정의를 피하고 여전히 객체를 불변으로 유지하므로 더 우아합니다.
답변
Java 5 이전에는 Map 솔루션이 이상적이지 않다는 것에 동의합니다. 컴파일 시간 유형 검사를 제공하지 않으므로 런타임에 문제가 발생할 수 있습니다. 그러나 Java 5에는 제네릭 형식이 있습니다.
따라서 방법은 다음과 같습니다.
public Map<String, MyType> doStuff();
물론 MyType은 반환하는 객체의 유형입니다.
기본적으로 나는 맵을 반환하는 것이 올바른 해결책이라고 생각합니다. 왜냐하면 그것이 반환하고자하는 것입니다-문자열을 객체에 매핑하는 것입니다.
답변
또는 메서드에서 여러 가지를 반환하려는 경우 컨테이너 대신 콜백 메커니즘을 사용하는 경우가 있습니다. 이것은 얼마나 많은 객체가 생성 될지 미리 지정할 수없는 상황에서 매우 잘 작동합니다.
특정 문제로 다음과 같이 보일 것입니다.
public class ResultsConsumer implements ResultsGenerator.ResultsCallback
{
public void handleResult( String name, Object value )
{
...
}
}
public class ResultsGenerator
{
public interface ResultsCallback
{
void handleResult( String aName, Object aValue );
}
public void generateResults( ResultsGenerator.ResultsCallback aCallback )
{
Object value = null;
String name = null;
...
aCallback.handleResult( name, value );
}
}