Как возвратить несколько объектов из метода Java?

165
задан James P. 2 July 2011 в 09:30
поделиться

11 ответов

Если Вы хотите возвратить два объекта, Вы обычно хотите возвратить отдельный объект, который инкапсулирует два объекта вместо этого.

Вы могли возвратить Список 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 мог бы быть тем, что Вы хотите.

123
ответ дан Evan Mulawski 23 November 2019 в 21:09
поделиться

ПЕРЕДАЙТЕ ХЕШ В МЕТОД И ЗАПОЛНИТЕ ЕГО......

общественность освобождают buildResponse (Строковые данные, ответ Карты);

-5
ответ дан l_39217_l 23 November 2019 в 21:09
поделиться

Для почему бы не создания WhateverFunctionResult, объект, который содержит результаты, и логика, требуемая проанализировать эти результаты, выполняет итерации тогда и т.д. Мне что также кажется:

  1. Эти объекты результатов глубоко связываются вместе/связанный и принадлежат вместе, или:
  2. они не связаны, в этом случае Ваша функция не четко определена с точки зрения того, что она пытается сделать (т.е. делает две разных вещи)

, я вижу, что этот вид проблемы неожиданно возникает снова и снова. Не бойтесь создать свои собственные классы контейнера/результата, которые содержат данные и связанную функциональность для обработки этого. Если Вы просто раздаете материал в HashMap или подобный, то Ваши клиенты должны разделить эту карту и grok содержание каждый раз, когда они хотят использовать результаты.

1
ответ дан Brian Agnew 23 November 2019 в 21:09
поделиться

Поскольку я вижу его существует действительно три варианта здесь, и решение зависит от контекста. Можно принять решение реализовать конструкцию имени в методе, который производит список. Это - выбор, который Вы выбрали, но я не думаю, что это - лучшее. Вы создаете связь в методе производителя к методу потребления, который не должен существовать. Другим вызывающим сторонам, возможно, не понадобится дополнительная информация, и Вы вычислили бы дополнительную информацию для этих вызывающих сторон.

, С другой стороны, у Вас мог быть вызывающий метод, вычисляют имя. Если существует только одна вызывающая сторона, которой нужна эта информация, можно остановиться там. У Вас нет дополнительных зависимостей и в то время как существует немного дополнительного включенного вычисления, Вы постарались не делать свой способ строительства слишком конкретным. Это - хороший компромисс.

Наконец, у Вас мог быть сам список быть ответственными за создание имени. Это - маршрут, я пошел бы, если вычисление должно быть сделано больше чем одной вызывающей стороной. Я думаю, что это помещает ответственность за создание имен с классом, который является самым тесно связанным с самими объектами.

В последнем случае, мое решение состояло бы в том, чтобы создать специализированный класс Списка, который возвращает разделенную от запятой строку названий объектов, которые это содержит. Сделайте класс достаточно умным, что он создает строку имени на лету, поскольку объекты добавлены и удалены из него. Тогда возвратите экземпляр этого списка и назовите метод поколения имени по мере необходимости. Хотя это может быть почти как эффективное (и более просто) для простой задержки вычисления имен до первого раза, когда метод называют, и сохраните его тогда (ленивая загрузка). Если Вы добавляете/удаляете объект, Вы должны только удалить расчетное значение и иметь оно повторно вычисляется на следующий вызов.

2
ответ дан tvanfosson 23 November 2019 в 21:09
поделиться

Мы должны забыть о маленькой эффективности, сказать приблизительно 97% времени: преждевременная оптимизация является корнем всего зла.

D. Knuth

10
ответ дан Jon Skeet 23 November 2019 в 21:09
поделиться

С другой стороны, в ситуациях, где я хочу возвратить много вещей из метода, я буду иногда использовать механизм обратного вызова вместо контейнера. Это работает очень хорошо в ситуациях, где я не могу определить загодя, сколько объектов будет сгенерировано.

С Вашей конкретной проблемой, это выглядело бы примерно так:

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 );
    }
}
6
ответ дан 23 November 2019 в 21:09
поделиться

Перед Java 5 я отчасти согласился бы, что решение для Карты не идеально. Это не дало бы Вам, тип времени компиляции, проверяющий так, может вызвать проблемы во времени выполнения. Однако с Java 5, у нас есть Универсальные Типы.

, Таким образом, Ваш метод мог быть похожим на это:

public Map<String, MyType> doStuff();

MyType, конечно, являющийся типом объекта, Вы возвращаетесь.

В основном я думаю, что возврат Карты является правильным решением в этом случае, потому что это точно, что Вы хотите возвратить - отображение строки к объекту.

9
ответ дан kipz 23 November 2019 в 21:09
поделиться

Я почти всегда заканчиваю тем, что определил классы 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 и все еще сохраняет объект неизменным.

15
ответ дан Ulrik Rasmussen 23 November 2019 в 21:09
поделиться

Если Вы знаете, что собираетесь возвратить два объекта, можно также использовать универсальную пару:

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.
  • я только что записал это в ответ на комментарии в целях иллюстрации только.
65
ответ дан jamesh 23 November 2019 в 21:09
поделиться

Все возможные решения будут клуджем (как контейнерные объекты, Ваша идея HashMap, “multiple возвращают values”, как понято через массивы). Я рекомендую повторно создать разделенный запятыми список из возвращенного Списка. Код закончит тем, что был намного более чистым.

3
ответ дан Bombe 23 November 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: