丑陋的java数据结构

时间:2009-04-21 14:34:38

标签: java data-structures

我创建了以下结构,它将唯一的double值映射到一对或多对整数:

   @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,拳击),它是如此冗长?

7 个答案:

答案 0 :(得分:5)

首先使用一对整数对的类。或者这是巧合,所有数组都包含一堆对吗?

第二件事是,可以从配置文件中读取这些初始化数据。

编辑:当我再次查看此代码时,我意识到双打作为地图中的键有些冒险。如果由于数学运算而产生双打,则不清楚它们是否与计算机相等(即使它们在数学意义上相等)。浮点数表示为计算机中的近似值。您很可能希望将值与间隔(示例0.0-0.3)相关联,而不是值本身。如果始终使用与数组中的键相同的常量,则可以避免麻烦。但是在这种情况下你也可以使用枚举,如果他将计算出的双精度数用作地图中的键,那么没有新的程序员遇到麻烦。

答案 1 :(得分:2)

创建另一个类来保存整数对,并使用列表存储它们:

Map<Double,List<MyPair>>

这些是任意的整数对,还是代表什么?如果是后者,那么恰当地命名。新类在Java中很便宜,良好的命名会降低维护成本。

编辑:为什么要创建HashMap的匿名子类?

答案 2 :(得分:0)

在我看来,

使用静态初始化程序会略好一些,尽管它对冗长度没有任何作用:

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
}

答案 3 :(得分:0)

你可以在Integer [] []周围打一个类,比如Point?

这会让你有一个

HashMap<Double, List<Point>>

答案 4 :(得分:0)

我将从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或其他指定对象,它可能会清理您的界面。因此,更具体地“输入”您的整数数组。

答案 5 :(得分:0)

你也可以尝试使用Builder;对于这种用途,Java并不像其他语言那样好......但是这里是FYI:

第一次曝光

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()”调用和double brace init,您可以尝试:

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));

修改

我使用过的名字可能并不那么有意义;盒装/非盒装转换仍然是一个问题,但这是Java的问题

答案 6 :(得分:0)

你在这里做的并不多。警告必须被压制;在实践中,除非您实际上计划序列化此对象,否则您永远不必担心serialVersionUID

拳击可以(也可能应该)使用类型集合删除,如此处其他答案中所述。要删除样板,您必须使用方法。例如:

private static void put (double key, int x, int y) {
  rules.put(key, new Point(x,y));
}