简体   繁体   English

看起来很丑的Java数据结构

[英]Ugly looking java data structure

I've created the following structure which maps unique double values to one or more pairs of integers: 我创建了以下结构,该结构将唯一的双精度值映射到一对或多对整数:

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

Can I rewrite this so it's simpler - ie not have to deal with warnings (serialVersionUID, boxing), and it being so verbose? 我可以重写它以便它更简单-即不必处理警告(serialVersionUID,装箱),并且它是如此冗长吗?

Using a class for the pairs of integers should be the first. 首先将一类用于整数对。 Or is this a coincidence, that all arrays containing a bunch of pairs? 还是所有数组都包含一对配对的巧合?

The second thing is, that these initialization-data could be read from a configuration-file. 第二件事是,可以从配置文件中读取这些初始化数据。

Edit: As I looked again on this code, I realized that Doubles as keys in a Map is somewhat risky. 编辑:当我再次查看此代码时,我意识到将Doubles用作Map中的键有些冒险。 If you produce Doubles as a result of an mathematical operation, it is not clear, if they will be equal for the computer (even if they are equal in a mathematical sense). 如果由于数学运算而产生Doubles,则不清楚它们是否与计算机相等(即使在数学意义上相等)。 Floating-point-numbers are represented as approximation in computers. 浮点数在计算机中表示为近似值。 Most likely you want to associate the values with the interval (example 0.0-0.3) and not the value itself. 您很可能希望将值与时间间隔(例如0.0-0.3)关联,而不是将值本身关联。 You may avoid trouble, if you always use the same constants as keys in the array. 如果您始终使用与数组中的键相同的常量,则可以避免麻烦。 But in this case you could use an enum as well, and no new programmer runs into trouble, if he uses his calculated doubles as keys in the map. 但是在这种情况下,您也可以使用一个枚举,并且如果新程序员将计算出的双精度数用作映射中的键,则不会遇到麻烦。

Create another class to hold your pairs of integers, and store them using a list: 创建另一个类来保存您的整数对,并使用列表进行存储:

Map<Double,List<MyPair>>

Are these to be arbitrary pairs of integers, or will the represent something? 这些是任意的整数对,还是表示某些东西? If the latter, then name appropriately. 如果是后者,请适当命名。 New classes are cheap in Java, and good naming will reduce maintenance costs. 新类在Java中很便宜,而且良好的命名将减少维护成本。

Edit: why are you creating an anonymous subclass of HashMap? 编辑:为什么要创建HashMap的匿名子类?

using a static initializer would be slightly better in my opinion, although it does nothing about the verbosity: 在我看来,使用静态初始值设定项会稍微好一些,尽管它对冗长性没有任何作用:

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

}

Another option using a special Pair class and Arrays.asList : 使用特殊的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
}

Can you wrap a class around Integer[][] called, say Point? 可以说一个围绕Integer [] []的类吗?

That would make you have a 那会让你有一个

HashMap<Double, List<Point>>

I would start with a MultiValueMap. 我将从MultiValueMap开始。 http://larvalabs.com/collections/ . http://larvalabs.com/collections/

This way you can do: 这样,您可以执行以下操作:

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

It looks also like you are aways using pairs of integers as the list of Keys. 看起来您也不用使用整数对作为“键”列表。 It would probably clean your interface up if you refered to that as a RulePair or some other specified object. 如果您将其称为RulePair或其他指定的对象,则可能会清理您的接口。 Thus 'typing' your Integer array more specificially. 因此,可以更具体地“键入”您的Integer数组。

you could try also with a Builder; 您也可以尝试使用Builder。 Java is not good as other languages for this kind of uses.. but here is FYI: Java在这种用途上不如其他语言那么好。.但在此仅供参考:

First shot 第一枪

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

sample usage: 样本用法:

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

Second shot 第二枪

In order to elimate the final "build()" call and double brace init you could try with: 为了消除最终的“ 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;
    }
}

in this case the code is a little better: 在这种情况下,代码要好一些:

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 编辑

Probably the names that I've used are not so meaningful; 我使用的名称可能没有那么有意义; boxed/unboxed conversion is still a problem but this is a problem of Java 装箱/拆箱转换仍然是一个问题,但这是Java的问题

There's not much you can do here. 在这里您无能为力。 The warnings have to be suppressed; 警告必须被禁止; in practice, you never have to worry about serialVersionUID unless you are in fact planning to serialize this object. 实际上,除非您实际上计划序列化该对象,否则您不必担心serialVersionUID

The boxing can (and probably should) be removed by using a typed collection as described in other answers here. 如此处其他答案所述,可以通过使用类型化的集合来删除拳击(可能应该删除)。 To remove the boilerplate, you'll have to use a method. 要删除样板,您必须使用一种方法。 For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM