Если Вы хотите возвратить два объекта, Вы обычно хотите возвратить отдельный объект, который инкапсулирует два объекта вместо этого.
Вы могли возвратить Список 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>
с ключами, являющимися именами и значениями объекты (если Ваши объекты не определили, что порядок, в этом случае NavigableMap
мог бы быть тем, что Вы хотите.
ПЕРЕДАЙТЕ ХЕШ В МЕТОД И ЗАПОЛНИТЕ ЕГО......
общественность освобождают buildResponse (Строковые данные, ответ Карты);
Для почему бы не создания WhateverFunctionResult
, объект, который содержит результаты, и логика, требуемая проанализировать эти результаты, выполняет итерации тогда и т.д. Мне что также кажется:
, я вижу, что этот вид проблемы неожиданно возникает снова и снова. Не бойтесь создать свои собственные классы контейнера/результата, которые содержат данные и связанную функциональность для обработки этого. Если Вы просто раздаете материал в HashMap
или подобный, то Ваши клиенты должны разделить эту карту и grok содержание каждый раз, когда они хотят использовать результаты.
В C++ (STL) там парный класс для связывания двух объектов. В Дженериках Java парный класс не доступен, хотя существуют [приблизительно 110] спрос для него. Вы могли легко реализовать его сами все же.
я соглашаюсь однако с некоторыми другими ответами, что, если бы необходимо возвратить два или больше объекта из метода, было бы лучше инкапсулировать их в классе.
Поскольку я вижу его существует действительно три варианта здесь, и решение зависит от контекста. Можно принять решение реализовать конструкцию имени в методе, который производит список. Это - выбор, который Вы выбрали, но я не думаю, что это - лучшее. Вы создаете связь в методе производителя к методу потребления, который не должен существовать. Другим вызывающим сторонам, возможно, не понадобится дополнительная информация, и Вы вычислили бы дополнительную информацию для этих вызывающих сторон.
, С другой стороны, у Вас мог быть вызывающий метод, вычисляют имя. Если существует только одна вызывающая сторона, которой нужна эта информация, можно остановиться там. У Вас нет дополнительных зависимостей и в то время как существует немного дополнительного включенного вычисления, Вы постарались не делать свой способ строительства слишком конкретным. Это - хороший компромисс.
Наконец, у Вас мог быть сам список быть ответственными за создание имени. Это - маршрут, я пошел бы, если вычисление должно быть сделано больше чем одной вызывающей стороной. Я думаю, что это помещает ответственность за создание имен с классом, который является самым тесно связанным с самими объектами.
В последнем случае, мое решение состояло бы в том, чтобы создать специализированный класс Списка, который возвращает разделенную от запятой строку названий объектов, которые это содержит. Сделайте класс достаточно умным, что он создает строку имени на лету, поскольку объекты добавлены и удалены из него. Тогда возвратите экземпляр этого списка и назовите метод поколения имени по мере необходимости. Хотя это может быть почти как эффективное (и более просто) для простой задержки вычисления имен до первого раза, когда метод называют, и сохраните его тогда (ленивая загрузка). Если Вы добавляете/удаляете объект, Вы должны только удалить расчетное значение и иметь оно повторно вычисляется на следующий вызов.
Мы должны забыть о маленькой эффективности, сказать приблизительно 97% времени: преждевременная оптимизация является корнем всего зла.
D. Knuth
С другой стороны, в ситуациях, где я хочу возвратить много вещей из метода, я буду иногда использовать механизм обратного вызова вместо контейнера. Это работает очень хорошо в ситуациях, где я не могу определить загодя, сколько объектов будет сгенерировано.
С Вашей конкретной проблемой, это выглядело бы примерно так:
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 );
}
}
Перед Java 5 я отчасти согласился бы, что решение для Карты не идеально. Это не дало бы Вам, тип времени компиляции, проверяющий так, может вызвать проблемы во времени выполнения. Однако с Java 5, у нас есть Универсальные Типы.
, Таким образом, Ваш метод мог быть похожим на это:
public Map<String, MyType> doStuff();
MyType, конечно, являющийся типом объекта, Вы возвращаетесь.
В основном я думаю, что возврат Карты является правильным решением в этом случае, потому что это точно, что Вы хотите возвратить - отображение строки к объекту.
Я почти всегда заканчиваю тем, что определил классы n-кортежа, когда я кодирую в Java. Например:
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 более изящен, поскольку он старается не определять методов get и все еще сохраняет объект неизменным.
Если Вы знаете, что собираетесь возвратить два объекта, можно также использовать универсальную пару:
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 сделает менее раздражающим. Существует некоторая работа для создания этого действительно хорошего ре: дженерики, но это должен быть хорошо-выход теперь. (c.f. ПЕЧ) hashcode
и equals
сгенерированы затмением. cast
метод в порядке, но не кажется совершенно правильным. isInstance
. Все возможные решения будут клуджем (как контейнерные объекты, Ваша идея HashMap, “multiple возвращают values”, как понято через массивы). Я рекомендую повторно создать разделенный запятыми список из возвращенного Списка. Код закончит тем, что был намного более чистым.