代码之家  ›  专栏  ›  技术社区  ›  JRL

丑陋的java数据结构

  •  3
  • JRL  · 技术社区  · 15 年前

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

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

    7 回复  |  直到 15 年前
        1
  •  5
  •   Mnementh    14 年前

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

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

    当我再次查看这段代码时,我意识到在地图中双重作为键有点危险。如果数学运算的结果是产生双倍数,则不清楚它们对于计算机是否相等(即使它们在数学意义上相等)。浮点数在计算机中表示为近似值。您很可能希望将值与间隔(例如0.0-0.3)关联,而不是与值本身关联。如果始终使用与数组中键相同的常量,则可以避免麻烦。但在这种情况下,您也可以使用enum,如果新程序员使用计算出的双倍数作为映射中的键,那么就不会遇到任何问题。

        2
  •  2
  •   kdgregory    15 年前

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

    Map<Double,List<MyPair>>
    

    这些是任意的整数对,还是表示某种东西?如果是后者,则适当命名。新类在Java中很便宜,良好的命名将降低维护成本。

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

        3
  •  0
  •   Nick Stinemates    15 年前

    你能把一个名为Point的整数[]类包装起来吗?

    HashMap<Double, List<Point>>
    
        4
  •  0
  •   andri    15 年前

    在我看来,使用静态初始值设定项会稍微好一点,尽管它对冗长性没有任何影响:

    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
    }
    
        5
  •  0
  •   Nathan Feger    15 年前

    我将从一个多值映射开始。 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;
       };
    

    看起来你也经常使用整数对作为键列表。如果您将其引用为规则对或其他指定对象,它可能会清理您的接口。因此,更具体地“键入”整数数组。

        6
  •  0
  •   Paul Brinkley    15 年前

    你在这里做不了什么。警告必须被压制;实际上,你永远不必担心 serialVersionUID 除非您实际上计划序列化此对象。

    可以(也可能应该)通过使用此处其他答案中描述的类型化集合来删除装箱。要删除样板文件,必须使用一种方法。例如:

    private static void put (double key, int x, int y) {
      rules.put(key, new Point(x,y));
    }
    
        7
  •  0
  •   dfa    15 年前

    第一枪

    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的一个问题