从 Java 中的行集创建树的最佳方法
Best way to create a tree from rowset in Java
假设我在 Java 中有一个列表列表,如下所示:
[
[A, AA, 10],
[A, AB, 11],
[B, BA, 20],
[A, AA, 12],
]
我想处理每一行以创建地图的地图,这样我就可以按如下方式处理每一行中的最后一个值:
{
A: {
AA: [10, 12]
AB: [11]
},
B: {
BA: [20]
}
}
通过这种方式,我可以进行如下调用:
for (int i : map.get("A").get("AA")) { ... }
当然,我可以遍历列表并手动创建地图。然而,这是一段非常难看的代码,很难将其概括为 3,4,5,...,n
列。
是否有一些巧妙的方法来处理此类列表?某种图书馆或其他我没有考虑过的东西?
又是一段丑陋的代码:-)
class CustomTree {
private final Map store;
private final int length;
public CustomTree(List<List<String>> source, int length) {
if (length < 2)
throw new IllegalArgumentException("Length must be greater than 2");
this.length = length;
this.store = new HashMap();
for (int i = 0; i < source.size(); i++) {
List<String> line = source.get(i);
if (line.size() != length)
throw new IllegalArgumentException(String.format("Line %d has wrong length", i));
}
for (List<String> line : source) {
if (line.size() != length)
throw new IllegalArgumentException("Not all lines have right length");
accumulate(store, line);
}
}
public void accumulate(Map parent, List<String> keys) {
String key = keys.get(0);
Object value = parent.get(key);
if (keys.size() == 2) {
parent.put(key, value != null
? addToList((List) value, keys.get(1))
: addToList(new ArrayList(), keys.get(1)));
} else {
Map child;
if (value != null) {
child = (Map) value;
} else {
child = new HashMap();
parent.put(key, child);
}
accumulate(child, keys.subList(1, keys.size()));
}
}
private List addToList(List list, String key) {
Integer intValue = Integer.valueOf(key);
if (!list.contains(intValue))
list.add(intValue);
return list;
}
public List<Integer> get(List<String> keys) {
if (keys.size() != (length - 1))
throw new IllegalArgumentException("Bad keys length");
return get(keys, store);
}
private List<Integer> get(List<String> keys, Map tree) {
Object object = tree.get(keys.get(0));
if (object == null)
return new ArrayList<Integer>(0);
return keys.size() == 1
? ((List<Integer>) object)
: get(keys.subList(1, keys.size()), (Map) object);
}
}
用法
public class Main {
public static void main(String[] args) {
List<List<String>> source = new ArrayList<List<String>>();
List<String> first = Arrays.asList("A", "AA", "CB", "10");
List<String> second = Arrays.asList("A", "AB", "CB", "11");
List<String> third = Arrays.asList("BA", "BA", "CB", "20");
List<String> fourth = Arrays.asList("A", "AA", "CB", "12");
List<String> fifth = Arrays.asList("BA", "BA", "CB", "21");
source.add(first);
source.add(second);
source.add(third);
source.add(fourth);
source.add(fifth);
CustomTree tree = new CustomTree(source, 4);
System.out.println(tree.get(Arrays.asList("BA", "BA", "CB")));
System.out.println(tree.get(Arrays.asList("BA", "B", "sf")));
}
}
可能太丑了。它仅在需要树的最终元素而没有任何中间 Map 时才有效。
假设我在 Java 中有一个列表列表,如下所示:
[
[A, AA, 10],
[A, AB, 11],
[B, BA, 20],
[A, AA, 12],
]
我想处理每一行以创建地图的地图,这样我就可以按如下方式处理每一行中的最后一个值:
{
A: {
AA: [10, 12]
AB: [11]
},
B: {
BA: [20]
}
}
通过这种方式,我可以进行如下调用:
for (int i : map.get("A").get("AA")) { ... }
当然,我可以遍历列表并手动创建地图。然而,这是一段非常难看的代码,很难将其概括为 3,4,5,...,n
列。
是否有一些巧妙的方法来处理此类列表?某种图书馆或其他我没有考虑过的东西?
又是一段丑陋的代码:-)
class CustomTree {
private final Map store;
private final int length;
public CustomTree(List<List<String>> source, int length) {
if (length < 2)
throw new IllegalArgumentException("Length must be greater than 2");
this.length = length;
this.store = new HashMap();
for (int i = 0; i < source.size(); i++) {
List<String> line = source.get(i);
if (line.size() != length)
throw new IllegalArgumentException(String.format("Line %d has wrong length", i));
}
for (List<String> line : source) {
if (line.size() != length)
throw new IllegalArgumentException("Not all lines have right length");
accumulate(store, line);
}
}
public void accumulate(Map parent, List<String> keys) {
String key = keys.get(0);
Object value = parent.get(key);
if (keys.size() == 2) {
parent.put(key, value != null
? addToList((List) value, keys.get(1))
: addToList(new ArrayList(), keys.get(1)));
} else {
Map child;
if (value != null) {
child = (Map) value;
} else {
child = new HashMap();
parent.put(key, child);
}
accumulate(child, keys.subList(1, keys.size()));
}
}
private List addToList(List list, String key) {
Integer intValue = Integer.valueOf(key);
if (!list.contains(intValue))
list.add(intValue);
return list;
}
public List<Integer> get(List<String> keys) {
if (keys.size() != (length - 1))
throw new IllegalArgumentException("Bad keys length");
return get(keys, store);
}
private List<Integer> get(List<String> keys, Map tree) {
Object object = tree.get(keys.get(0));
if (object == null)
return new ArrayList<Integer>(0);
return keys.size() == 1
? ((List<Integer>) object)
: get(keys.subList(1, keys.size()), (Map) object);
}
}
用法
public class Main {
public static void main(String[] args) {
List<List<String>> source = new ArrayList<List<String>>();
List<String> first = Arrays.asList("A", "AA", "CB", "10");
List<String> second = Arrays.asList("A", "AB", "CB", "11");
List<String> third = Arrays.asList("BA", "BA", "CB", "20");
List<String> fourth = Arrays.asList("A", "AA", "CB", "12");
List<String> fifth = Arrays.asList("BA", "BA", "CB", "21");
source.add(first);
source.add(second);
source.add(third);
source.add(fourth);
source.add(fifth);
CustomTree tree = new CustomTree(source, 4);
System.out.println(tree.get(Arrays.asList("BA", "BA", "CB")));
System.out.println(tree.get(Arrays.asList("BA", "B", "sf")));
}
}
可能太丑了。它仅在需要树的最终元素而没有任何中间 Map 时才有效。