Гадкий вид структуры данных Java - PullRequest
3 голосов
/ 21 апреля 2009

Я создал следующую структуру, которая отображает уникальные двойные значения на одну или несколько пар целых чисел:

   @SuppressWarnings("boxing")
   private static final HashMap<Double, Integer[][]> rules =
      new HashMap<Double, Integer[][]>() {
         private static final long serialVersionUID = 1L;
         {
            put(-0.6, new Integer[][] { { 1, 3 } });
            put(-0.3, new Integer[][] { { 2, 2 } });
            put(0.0, new Integer[][] { { 2, 4 }, { 3, 3 }, { 4, 2 } });
            put(0.3, new Integer[][] { { 4, 4 } });
            put(0.6, new Integer[][] { { 5, 3 } });
         }
   };

Могу ли я переписать это так, чтобы оно было проще - то есть не нужно иметь дело с предупреждениями (serialVersionUID, boxing), и оно настолько многословно?

Ответы [ 7 ]

5 голосов
/ 21 апреля 2009

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

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

Редактировать: Когда я снова посмотрел на этот код, я понял, что Doubles как ключи на карте несколько рискованно. Если вы производите Double в результате математической операции, не ясно, будут ли они равны для компьютера (даже если они равны в математическом смысле). Числа с плавающей точкой представлены в компьютерах как приближение. Скорее всего, вы хотите связать значения с интервалом (пример 0.0-0.3), а не само значение. Вы можете избежать проблем, если всегда используете те же самые константы, что и ключи в массиве. Но в этом случае вы также можете использовать enum, и ни у одного программиста не возникнет проблем, если он использует свои вычисленные двойники в качестве ключей на карте.

2 голосов
/ 21 апреля 2009

Создайте другой класс для хранения ваших пар целых чисел и сохраните их, используя список:

Map<Double,List<MyPair>>

Это произвольные пары целых чисел, или они будут представлять что-то? Если последнее, то назови соответственно. Новые классы в Java дешевы, а хорошее именование сократит затраты на обслуживание.

Редактировать: почему вы создаете анонимный подкласс HashMap?

0 голосов
/ 21 апреля 2009

Здесь мало что можно сделать. Предупреждения должны быть подавлены; на практике вам никогда не придется беспокоиться о serialVersionUID, если вы на самом деле не планируете сериализовать этот объект.

Бокс может (и, вероятно, должен) быть удален с использованием типизированной коллекции, как описано в других ответах здесь. Чтобы удалить шаблон, вы должны будете использовать метод. Например:

private static void put (double key, int x, int y) {
  rules.put(key, new Point(x,y));
}
0 голосов
/ 21 апреля 2009

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

Первый выстрел

class RuleBuilder  {

    private Map<Double, Integer[][]> rules;

    public RuleBuilder() {
        rules = new HashMap<Double, Integer[][]>();
    }

    public RuleBuilder rule(double key, Integer[]... rows) {
        rules.put(key, rows);
        return this;
    }

    public Integer[] row(Integer... ints) {
        return ints;
    }

    public Map<Double, Integer[][]> build() {
        return rules;
    }
}

пример использования:

private static final Map<Double, Integer[][]> rules = 
                new RuleBuilder() {{
                    rule(-0.6, row(1, 3));                        
                    rule(-0.3, row(2, 2));
                    rule(0.0, row(2, 4), row(3,3), row(4, 2));
                    rule(0.3, row(4, 4));
                    rule(0.6, row(5, 3));
                }}.build();

Второй выстрел

Чтобы упростить последний вызов "build ()" и инициализация двойной скобки , вы можете попробовать:

class RuleBuilder2 extends HashMap<Double, Integer[][]>  {

    public RuleBuilder2 rule(double key, Integer[]... rows) {
       put(key, rows);
       return this;
    }

    public Integer[] row(Integer... ints) {
        return ints;
    }
}

в этом случае код немного лучше:

private static final Map<Double, Integer[][]> rules2 =
                new RuleBuilder2().
                    rule(-0.6, row(1, 3)).
                    rule(-0.3, row(2, 2)).
                    rule(0.0, row(2, 4), row(3,3), row(4, 2)).
                    rule(0.3, row(4, 4)).
                    rule(0.6, row(5, 3));

EDIT

Возможно, имена, которые я использовал, не столь значимы; преобразование в штучной упаковке / без коробки - все еще проблема, но это проблема Java

0 голосов
/ 21 апреля 2009

Я бы начал с MultiValueMap. http://larvalabs.com/collections/.

Таким образом, вы можете сделать:

private static final MultiValueMap<Double, Integer[]> rules;
   static {
      MultiValueMap<Double, Integer[]> map = new MultiValueMap <Double, Integer[]>();

      map.put(-0.6, new Integer[] { 1, 3 });
      map.put(-0.3, new Integer[] { 2, 2 });
      map.put(0.0, new Integer[]  { 2, 4 }, new Integer[]{ 3, 3 }, new Integer[]{ 4, 2 } );
      map.put(0.3, new Integer[]  { 4, 4 } );
      map.put(0.6, new Integer[]  { 5, 3 } );
      rules = map;
   };

Похоже, что вы всегда используете пары целых чисел в качестве списка ключей. Вероятно, он очистил бы ваш интерфейс, если бы вы ссылались на него как на RulePair или какой-то другой указанный объект. Таким образом, «печатая» ваш массив Integer более конкретно.

0 голосов
/ 21 апреля 2009

Можете ли вы обернуть класс в Integer [] [] с именем Point, скажем?

Это сделало бы у вас

HashMap<Double, List<Point>>
0 голосов
/ 21 апреля 2009

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

private static final Map<Double, int[][]> rules;

static {
    rules = new HashMap<Double, int[][]>();

    rules.put(-0.6, new int[][] { { 1, 3 } });
    rules.put(-0.3, new int[][] { { 2, 2 } });
    rules.put(0.0, new int[][] { { 2, 4 }, { 3, 3 }, { 4, 2 } });
    rules.put(0.3, new int[][] { { 4, 4 } });
    rules.put(0.6, new int[][] { { 5, 3 } });

}

Другой вариант, использующий специальный класс Pair и Arrays.asList:

class Pair<A, B> {
  A a;
  B b;

  public Pair(A fst, B snd) {
  }

  // getters and setters here
}

private static final Map<Double, List<Pair<Integer, Integer>>> rules;

static {
    rules = new HashMap<Double, List<Pair<Integer, Integer>>>();

    rules.put(-0.6, Arrays.asList(new Pair(1, 3)));
    rules.put(-0.3, Arrays.asList(new Pair(2, 2)));
    rules.put(0.0, Arrays.asList(new Pair(2, 4), new Pair(3, 3), new Pair(4, 2));
    // etc
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...