丑陋的java数据结构
我创建了以下结构,将唯一的双精度值映射到一对或多对整数:丑陋的java数据结构,java,data-structures,Java,Data Structures,我创建了以下结构,将唯一的双精度值映射到一对或多对整数: @SuppressWarnings("boxing") private static final HashMap<Double, Integer[][]> rules = new HashMap<Double, Integer[][]>() { private static final long serialVersionUID = 1L; {
@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 } });
}
};
@SuppressWarnings(“装箱”)
私有静态最终哈希映射规则=
新HashMap(){
私有静态最终长serialVersionUID=1L;
{
put(-0.6,新整数[][{{1,3}});
put(-0.3,新整数[][{{2,2}});
put(0.0,新整数[][{{2,4},{3,3},{4,2});
put(0.3,新整数[][{4,4});
put(0.6,新整数[][{{5,3});
}
};
我是否可以重写它以使其更简单—即不必处理警告(serialVersionUID、boxing),而且它非常冗长?创建另一个类来保存整数对,并使用列表存储它们:
Map<Double,List<MyPair>>
Map
这些是任意的整数对,还是表示某种东西?如果是后者,则适当命名。新类在Java中很便宜,良好的命名将降低维护成本
编辑:为什么要创建HashMap的匿名子类?在我看来,使用静态初始值设定项会稍微好一点,尽管它对详细性没有任何影响:
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 } });
}
你能把一个名为Point的整数[]类包装起来吗 那会让你有一个
HashMap<Double, List<Point>>
HashMap
我将从多值映射开始
通过这种方式,您可以:
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;
};
私有静态最终多值映射规则;
静止的{
多值映射=新的多值映射();
put(-0.6,新整数[]{1,3});
put(-0.3,新整数[]{2,2});
put(0.0,新整数[]{2,4},新整数[]{3,3},新整数[]{4,2});
put(0.3,新整数[]{4,4});
put(0.6,新整数[]{5,3});
规则=地图;
};
看起来你也经常使用整数对作为键列表。如果您将其引用为规则对或其他指定对象,它可能会清理您的接口。因此,更具体地“键入”整数数组。首先应该为整数对使用类。或者这是巧合,所有数组都包含一组对 第二件事是,这些初始化数据可以从配置文件中读取
编辑:当我再次查看这段代码时,我意识到在地图中双重作为键有点危险。如果数学运算的结果是产生双倍数,则不清楚它们对于计算机是否相等(即使它们在数学意义上相等)。浮点数在计算机中表示为近似值。您很可能希望将值与间隔(例如0.0-0.3)关联,而不是与值本身关联。如果始终使用与数组中键相同的常量,则可以避免麻烦。但在这种情况下,您也可以使用枚举,如果新程序员在地图中使用计算出的双精度作为键,那么他不会遇到麻烦。您也可以尝试使用生成器;在这种用途上,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;
}
}
类规则生成器{
私有地图规则;
公共规则生成器(){
rules=newhashmap();
}
公共规则生成器规则(双键,整数[]…行){
规则。放置(键,行);
归还这个;
}
公共整数[]行(整数…整数){
返回整数;
}
公共地图构建(){
退货规则;
}
}
示例用法:
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();
私有静态最终映射规则=
新规则生成器(){{
规则(-0.6,第(1,3)行);
规则(-0.3,第(2,2)行);
规则(0.0,第(2,4)行,第(3,3)行,第(4,2)行);
规则(0.3,第(4,4)行);
规则(0.6,第(5,3)行);
}}.build();
第二枪
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;
}
}
为了省略最后的“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;
}
}
类RuleBuilder2扩展了HashMap{
公共规则生成器2规则(双键,整数[]…行){
放置(键,行);
归还这个;
}
公共整数[]行(整数…整数){
返回整数;
}
}
在这种情况下,代码稍微好一点:
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));
私有静态最终映射规则2=
新建RuleBuilder2()。
规则(-0.6,第(1,3)行)。
规则(-0.3,第(2,2)行)。
规则(0.0,第(2,4)行,第(3,3)行,第(4,2)行)。
规则(0.3,第(4,4)行)。
规则(0.6,第(5,3)行);
编辑
也许我用过的名字没有那么有意义;装箱/未装箱转换仍然是一个问题,但这是Java的一个问题在这里您可以做的不多。警告必须被压制;实际上,您永远不必担心
serialVersionUID
,除非您实际上计划序列化此对象
可以(也可能应该)通过使用此处其他答案中描述的类型化集合来删除装箱。要删除样板文件,必须使用一种方法。例如:
private static void put (double key, int x, int y) {
rules.put(key, new Point(x,y));
}
但为了避免警告,所有对都必须构造为新对(x,y)。在这种情况下,我更喜欢一双特制的。我忘了将类型参数添加到实例化中;一个特殊的pair类确实会更好。或者你可以添加一个
of
方法,这样你就有了of(1,3)
或者甚至of(1,3)
。代码是用来干什么的?这看起来像是原始的困扰代码气味。这是一组用于视觉引导机器人运动的模糊逻辑控制器的简化规则。是否有任何理由使用整数[]而不是int[]]?@Peter:没有,只是为了使用HashMap。@JRL:Peter Lawrey的意思是int[]]作为泛型参数是完全可以接受的,而且可以避免大量的自动装箱/