在Java中将值(“ o”)保留在像这样的树结构中的最佳方法是什么:
obj1 /\ / \ / \ obj2 obj3 /\ /\ / \ / \ / \ / \ obj4 obj5 obj6 obj7 /\ /\ /\ /\ / \ / \ / \ / \ o8 oN...
它看起来像一棵树,但是我不需要任意深度。我宁愿需要强大的数据类型和预定义的美观方法来处理最终结构。
我需要能够通过键获取某种值列表-就像在我的图片上一样。换句话说,结构应 不 以任何方式变得平坦。
我需要.get(obj3)回来{obj6, obj7}, .get(obj1) - {obj2, obj3}。
.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); }
性能不是问题,但是代码美才是。
您可以使用您的特定密钥:
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()。它可以使客户端代码保持干净,并且关键的复杂性放在安全的地方。
MyKey.equals()
如果最重要的是,您希望能够获得从双beta精度对象到对象的映射,那么我仍然会像这样保持平面。
beta
您真正想要的是为数据提供多个“索引”(例如在数据库中),以便您可以查询具有相同“ beta”或“ yaw”的对象。为此,最好的方法是使用多个Map(实际上是Multimap),每个“索引”使用一个。
使用番石榴的Multimap:
ListMultimap<Double, Data> mapForBeta; ListMultimap<Double, Data> mapForYaw;
您可以将所有的multimap和Map<MyKey, Data>放在您的特定类中。实际上,最好的方法是子类化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)访问数据,并且没有意大利面条代码来存储您的值。