Java中的多级地图[重复]
Posted
技术标签:
【中文标题】Java中的多级地图[重复]【英文标题】:Multilevel map in Java [duplicate] 【发布时间】:2013-02-01 15:40:21 【问题描述】:在 Java 中将值(“o”)保存在这样的树结构中的最佳方法是什么:
obj1
/\
/ \
/ \
obj2 obj3
/\ /\
/ \ / \
/ \ / \
obj4 obj5 obj6 obj7
/\ /\ /\ /\
/ \ / \ / \ / \
o8 oN...
它看起来像一棵树,但我不需要任意深度。我宁愿需要强大的数据类型和预定义好看的方法来处理最终结构。
我需要能够通过键获得某种值列表 - 就像我的图片一样。换句话说,结构应该不以任何方式变为平面。
我需要.get(obj3)
才能返回obj6, obj7, .get(obj1) - obj2, obj3
。
现在我使用 Map 来做这件事,但是膨胀这样的地图很难看,因为我需要检查结构的每一层。看起来像这样(数据是地图):
if(data.get(somedouble) == null)
Map<Integer, Data> inm = new TreeMap<>();
inm.put(someint, obj);
Map<Double, Map<Integer, Data>> m = new TreeMap<>();
m.put(somedouble2, inm);
data.put(somedouble, m);
else
if(data.get(somedouble).get(somedouble2) == null)
Map<Integer, Data> inm = new TreeMap<>();
inm.put(someint, obj);
data.get(somedouble).put(somedouble2, inm);
else
data.get(somedouble).get(somedouble2).put(someint, obj);
性能不是问题,但代码美观才是问题。
【问题讨论】:
是的,它会简化使用这样的地图,但它如何帮助我摆脱对创建的冗长的多级检查? duffymo,我想过(其实我只是需要一些特殊的哈希和相等函数),但是对于这么简单的任务来说,工作量似乎太大了。 “平面”是什么意思并不明显。你能重述一下吗? 我想知道规范会再次更改多少次。 我现在要停下来。再次抱歉。 【参考方案1】:您可以使用您的特定密钥:
class MyKey
Double beta;
Double yaw;
int minute;
public int hashCode()
/* Returns hash code from a combination of hash of the key members. */
@Override
public boolean equals(Object obj)
/* Returns true if obj is a MyKey with same members. */
然后简单地说:
data.put(myKey, obj);
这样“多级检查”都隐藏在MyKey.equals()
中。它使客户端代码保持干净,并将关键复杂性放在一个安全的地方。
需求变更后编辑:
如果除此之外,您希望能够将您的双 beta
映射到您的对象,那么我仍然会保持这样的平面。
您真正想要的是为您的数据创建多个“索引”,例如在数据库中,这样您就可以查询具有相同“beta”或“yaw”的对象。为此,最好的方法是使用多个 Map(实际上是 Multimap),每个“索引”一个。
使用Guava's Multimap:
ListMultimap<Double, Data> mapForBeta;
ListMultimap<Double, Data> mapForYaw;
您可以将所有多图和Map<MyKey, Data>
放在您的特定类中。实际上最好的方法是继承Map<MyKey, Data>
:
public class MyMap extends HashMap<MyKey, Data>
ListMultimap<Double, Data> mapForBeta;
ListMultimap<Double, Data> mapForYaw;
public Data put(MyKey key, Data value)
super.put(key, value);
mapForBeta.add(key.beta, value);
mapForYaw.add(key.yaw, value);
;
public List<Data> getFromBeta(Double beta)
return mapForBeta.get(beta);
public List<Data> getFromYaw(Double yaw)
return mapForYaw.get(yaw);
具有更好解决方案的新编辑:
实际上,这让我开始思考,我意识到您的地图默认值确实存在问题,这就是您的代码有点混乱的原因。
您可以通过使用生成器创建底层地图的默认地图来解决此问题:
public class DefaultMap<K, V> extends TreeMap<K, V>
static abstract class Generator<V>
abstract V create();
final Generator<V> generator;
DefaultMap(Generator<V> generator)
this.generator = generator;
@Override
public V get(Object key)
V val = super.get(key);
if (val == null)
val = generator.create();
put((K)key, val);
return val;
现在您可以使用实用程序树类来存储所有数据:
public class MyTree
private final Map<Double, Map<Double, Map<Integer, Data>>> data;
public MyTree()
data = new DefaultMap<>(new Generator<Map<Double, Map<Integer, Data>>>()
@Override
Map<Double, Map<Integer, Data>> create()
return new DefaultMap<>(new Generator<Map<Integer, Data>>()
@Override
Map<Integer, Data> create()
return new TreeMap<>();
);
);
void add(MyKey d, Data obj)
data.get(d.beta).get(d.yaw).put(d.minute, obj);
现在您可以使用 data.get(beta).get(yaw) 访问您的数据,并且您没有意大利面条式代码来存储您的值。
【讨论】:
我担心规范会发生变化,根据我对我的回答的评论,“但是我如何通过 double d1 获得所有值?” 完成。规范已更改。 我明白了。好吧,我可能有点固执,但是加上一点,我认为我的解决方案仍然是最好的。 :) 那么 getByYaw 和 Beta 呢?像这样:data.get(double1).get(double2).get(int) 好吧,你总是可以有另一个 YawBetaKey 和另一个 Multimap 来存储关系。但我明白你的意思。我喜欢我的东西,因为你可以创建像 getFromBetaAndYaw() 之类的命名良好的方法。【参考方案2】:二叉树呢?
Node.java
public class Node
private Node leftChild;
private Node rightChild;
public Node(Node leftChild, Node rightChild)
this.leftChild = leftChild;
this.rightChild = rightChild;
public boolean isLeaf()
return this instanceof Leaf;
Leaf.java
public class Leaf extends Node
private Data data;
public Leaf(Data data)
super(null, null);
this.data = data;
例如,如果您要构建到以下树:
root
/\
/ \
/ \
node1 node2
/\ /\
/ \ / \
leaf1 leaf2 leaf3 leaf4
用途:
Leaf leaf1 = new Leaf(new Data());
Leaf leaf2 = new Leaf(new Data());
Leaf leaf3 = new Leaf(new Data());
Leaf leaf4 = new Leaf(new Data());
Node node1 = new Node(leaf1, leaf2);
Node node2 = new Node(leaf3, leaf4);
Node root = new Node(node1, node2);
【讨论】:
"data" 是一种 Map,不是二叉树。以上是关于Java中的多级地图[重复]的主要内容,如果未能解决你的问题,请参考以下文章