Есть ли способ закодировать перестановку целых чисел - PullRequest
5 голосов
/ 16 декабря 2010

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

    int numerator2 = <some random number>;
    int denominator2 = <some random number>;

    if (numerator2 > denominator2) {
        int temp = denominator2;
        denominator2 = numerator2;
        numerator2 = temp;
    }

Ответы [ 7 ]

4 голосов
/ 16 декабря 2010

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

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

  • В некоторых языках это можно сделать с помощью вызова по ссылке (например, FORTRAN) или передачи параметров INOUT (например, ObjectiveC):

    int a = 1;
    int b = 2;
    swap(a, b);
    
  • В некоторых языках вы можете имитировать вызов по ссылке, передавая адреса (например, C и C ++):

    int a = 1;
    int b = 2;
    swap(&a, &b);
    
  • В некоторых языках есть оператор присваивания кортежей (например, Perl):

    int a = 1;
    int b = 2;
    a, b = {b, a};
    // or ...
    a, b = swap(b, a); // where swap returns an explicit or implicit tuple.
    
  • В некоторых языках процедуры / методы могут возвращать несколько результатов, и существует специальный синтаксис для присвоения отдельных результатов другой переменной (например, Mesa ... и я уверен, что есть менее смутные примеры): 1024 *

    int a = 1;
    int b = 2;
    a, b = swap(b, a);
    

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

   IntHolder a = new IntHolder(1);
   IntHolder b = new IntHolder(2);
   swap(a, b);

Followup

Можно использовать существующие типы, такие как AtomicType или Apache Commons 'MutableInteger, в качестве класса-оболочки. Я бы порекомендовал последний, так как он немного быстрее. Кроме того, использование AtomicType экземпляров не означает, что вы можете реализовать метод swap атомарно.

3 голосов
/ 16 декабря 2010

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

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

2 голосов
/ 16 декабря 2010

Краткая версия ответа @ Emil:

public static void swap(AtomicInteger i,AtomicInteger j) {
    j.set(i.getAndSet(j.get()));
}

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

2 голосов
/ 16 декабря 2010

Разве примитивные типы не будут самым быстрым способом?Примитивы создаются в стеке и зачем создавать объекты?

1 голос
/ 16 декабря 2010

Вы можете использовать AtomicInteger или любой созданный пользователем объект-оболочку, который будет содержать значение int.Тогда вы можете написать swap метод.

1 голос
/ 16 декабря 2010

Вы можете использовать AtomicInteger или написать собственный MutableInteger вместо использования примитива int.

Код:

void swap(AtomicInteger i,AtomicInteger j){
        int tmp=i.get();
        i.set(j.get());
        j.set(tmp);
    }
0 голосов
/ 09 мая 2012

Я бы предложил придерживаться примитивной версии.

Причины:

  • Лучшая производительность за счет исключения упаковщиков
  • Это такая распространенная идиома, что вы легко можете мысленно проанализировать код подкачки
  • Сохранение 30 символов или около того ввода не оправдывает ИМХО добавление дополнительного уровня абстракции. Если вы включили преобразование в типы-обертки, вы, возможно, вообще не сохранили набор текста.
  • Вы можете легко написать своп в одну строку, если вас беспокоит вертикальное пространство

, например

if (numerator2 > denominator2) {
    int t = denominator2; denominator2 = numerator2; numerator2 = t;
}

Если вам нравятся забавные хаки, здесь также есть способ сделать это в одном выражении, используя порядок операций:

numerator2= denominator2+ (0&(denominator2=numerator2));

Конечно, это не очень рекомендуется, если вы заботитесь о читабельности / обслуживании: -)

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