Java: Как реализовать метод, который принимает 2 массива и возвращает 2 массива? - PullRequest
2 голосов
/ 04 мая 2010

Хорошо, вот что я хочу сделать:

Я хочу реализовать метод кроссовера для массивов.

Предполагается взять 2 массива одинакового размера и вернуть два новых массива, которые представляют собой некое сочетание двух входных массивов. как в [a, a, a, a] [b, b, b, b] ------> [a, a, b, b] [b, b, a, a].

Теперь мне интересно, как бы это было предложено в Java, поскольку я не могу вернуть более одного значения.

Мои идеи: - возвращает коллекцию (или массив), содержащую оба новых массива.

Мне не очень нравится этот, потому что он думает, что в результате будет сложнее понять код. - избегая необходимости возвращать два результата, вызывая метод для каждого случая, но получая только один из результатов каждый раз.

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

Плюс, это будет работать только для этого базового случая, но я хочу перетасовать массив перед кроссовером и затем перевернуть его. Я не могу сделать перетасовку изолированно от кроссовера, так как я не хочу фактически выполнять операцию, вместо этого я хочу использовать информацию о перестановке при выполнении кроссовера, что, я думаю, будет более эффективным способом.

Мой вопрос не о самом алгоритме, а о том, как вставить метод (относительно ввода и вывода) в Java

Ответы [ 10 ]

11 голосов
/ 04 мая 2010

Следуя предложению из книги Брюса Эккеля Мышление на Java , в мои проекты Java я часто включаю некоторые служебные классы для упаковки групп из двух или трех объектов. Они тривиальны и удобны, особенно для методов, которые должны возвращать несколько объектов. Например:

public class Pair<TA,TB> {
    public final TA a;
    public final TB b;

    /**
     * factory method
     */
    public static <TA,TB> Pair<TA,TB> createPair(TA a,TB b ){
        return new Pair<TA,TB>(a,b);
    }

    /**
     * private constructor - use instead factory method 
     */
    private Pair(final TA a, final TB b) {
            this.a = a;
            this.b = b; 
    }

    public String toString() {  
        return "(" + a + ", " + b + ")";
    }

}
6 голосов
/ 04 мая 2010

Прочитайте последний раздел этой статьи:

http://www.yoda.arachsys.com/java/passing.html

Цитировать:

Это настоящая причина, почему мимо ссылка используется во многих случаях - это позволяет метод эффективно много возвращаемых значений. Java не позволяет несколько «реальных» возвращаемых значений, и это не позволяет передавать по ссылке семантика, которая будет использоваться в других языки с одним возвращаемым значением. Тем не менее, вот некоторые методы обойти это:

  1. Если любое из ваших возвращаемых значений является кодами состояния, которые указывают на успех или отказ метода, устранить их немедленно. Замените их обработка исключений, которая бросает исключение, если метод не завершить успешно. Исключение это более стандартный способ обработки условия ошибки, может быть больше выразительным, и устраняет один из ваших возвращаемые значения.

  2. Найти связанные группы возвращаемых значений и инкапсулировать их в объекты, которые содержат каждый кусок информация в виде полей . Классы для эти объекты могут быть расширены до инкапсулировать их поведение позже, чтобы дальнейшее улучшение дизайна код. Каждый набор связанных возвращения значения, которые вы инкапсулируете в объект удаляет возвращаемые значения из метод повышения уровня абстракция интерфейса метода. Например, вместо прохождения координаты X и Y со ссылкой на разрешить их вернуть, создать изменяемый класс Point, передать объект ссылку на значение и обновите значения объекта в методе.

В качестве бонуса этот раздел обновил Джон Скит:)

5 голосов
/ 04 мая 2010

Если для вызывающего абонента разумно заранее знать размер возвращаемых массивов, вы можете передать их в метод:

     public void foo(Object[] inOne, Object[] inTwo, Object[] outOne, Object[] outTwo) {
            //etc.
     }

При этом более чем в 90% случаев множественные возвращаемые значения из метода скрывают лучший дизайн. Мое решение было бы сделать преобразование внутри объекта:

     public class ArrayMixer {
           private Object[] one;
           private Object[] two;
           public ArrayMixer(Object[] first, Object[] second) {
                //Mix the arrays in the constructor and assign to one and two.
           }
           public Object[] getOne() { return one; }
           public Object[] getTwo() { return two; }
     }

Я подозреваю, что в вашем реальном случае класс и массив один и массив два могут получить лучшие имена.

3 голосов
/ 04 мая 2010

Лучший способ сделать это - сделать

public void doStuff(int[] array1, int[] array2) {
    // Put code here
}

Поскольку Java-массивы в Java передают ссылку, любые изменения, сделанные в массивах, будут выполняться в самом массиве. Это имеет несколько предостережений

  1. Если вы устанавливаете его в null, вы должны использовать другой способ (например, заключить его в объект)
  2. Если вы инициализируете массив (в методе), вы должны использовать другой способ

Вы бы использовали это в формате:

// other method
int[] array1 = new int[20];  // the arrays can be whatever size
int[] array2 = new int[20];

doStuff(array1,array2);

// do whatever you need to with the arrays

Редактировать: Предполагается, что можно вносить изменения во входные массивы.

Если это не так, то объект (например, в ответе Леонблоя, безусловно, то, что нужно).

3 голосов
/ 04 мая 2010

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

Я думаю, что наиболее естественным выбором возвращаемого значения является int[][] длины 2 (замените int тем, какой тип вы используете). Я не вижу причин, по которым это должно усложнить понимание кода, особенно если вы укажете, каким будет содержимое возвращаемого значения.

Редактировать : в ответ на ваш комментарий я понимаю, что вы учли это, и я говорю, что, несмотря на ваши стилистические возражения, я не верю, что существует строго «лучшая» альтернатива "здесь, будучи свободно определенным в вопросе).

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

0 голосов
/ 04 мая 2010

Простое решение вышеуказанной проблемы - возврат в виде карты. Уловка этого вопроса заключается в том, как вы будете определять ключи для идентификации объектов, скажем, есть два входные массивы [a, a, a, a] [b, b, b, b] и два выходных массива [a, a, b, b] [b, b, a, a]

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

   Map<String,String[]> method(String[] x,String[] y){

do your stuff..........

   Hashmap<String,String[]> map =new HashMap<String,String[]>();
map.put("Object2",[b,b,a,a]);

return map;
}
0 голосов
/ 04 мая 2010

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

0 голосов
/ 04 мая 2010

Самый простой и понятный способ - создать бин-контейнер, содержащий два массива, и вернуть контейнер из метода.Вероятно, я бы также передал контейнер в метод, чтобы он оставался симметричным.

Самый эффективный способ памяти, если предположить, что оба массива имеют одинаковую длину, - передать многомерный массив - Object [2][n] - где n - длина массивов.

0 голосов
/ 04 мая 2010

Вы можете передать выходные массивы как параметры в метод. Это может дать вам больший контроль над распределением памяти для массивов.

0 голосов
/ 04 мая 2010

Вы строго не можете вернуть более одного значения (думаю, объект или примитив) в Java. Может быть, вы могли бы вернуть экземпляр определенного объекта «Результат», который имеет два массива в качестве свойств?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...