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);
}
性能不是问题,但代码美是。
答案 0 :(得分:6)
您可以使用特定密钥:
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),每个“索引”一个。
ListMultimap<Double, Data> mapForBeta;
ListMultimap<Double, Data> mapForYaw;
您可以将所有multimap和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)访问您的数据,并且您没有意大利面条代码来存储您的值。
答案 1 :(得分:1)
二叉树怎么样?
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);