我想在有序的Multimap
中安排List
中的值。所有键都在左侧,所有值都在右侧。我已经使用递归来实现这一点。但为此我必须将List
传递给返回void
的递归函数,但List
在我不喜欢的函数中被修改,是否有任何改进的方法此?
以下是我的示例代码
private static void getChilds(String col, List<String> list, Multimap<String, String> map) {
list.add(col);
Collection<String> String = map.get(col);
if (!String.isEmpty()) {
String.stream().forEach(col1 -> getChilds(col1, list, map));
}
}
private static List<String> getList(Multimap<String, String> map) {
Set<String> strings = map.keySet();
List<String> list = new ArrayList<>();
for (String string : strings) {
if (!map.containsValue(string)) {
getChilds(string, list, map);
}
}
return list;
}
public static void main(String[] args) {
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
map.put("P1", "P2");
map.put("P1", "P3");
map.put("P1", "P4");
map.put("P3", "P5");
map.put("P3", "P6");
map.put("P7", "P8");
map.put("P7", "P9");
System.out.println(getList(map));
}
Output : [P1, P2, P3, P5, P6, P4, P7, P8, P9]
请建议是否有任何好的方法,我不会违反任何干净的代码原则,仍然可以获得理想的结果。
因此,如果我们在地图中添加一个新条目,如
map.put("P10", "P1");
然后输出的相应变化将是
Output : [P7, P8, P9, P10, P1, P2, P3, P5, P6, P4]
答案 0 :(得分:0)
左侧的所有键和列表右侧的所有值:
List<String> result = new LinkedList<String>();
for (Entry<String, String> entry : map.entries())
{
if (!result.contains(entry.getValue()))
{
result.addLast(entry.getValue());
}
if (!result.contains(entry.getKey()))
{
result.addFirst(entry.getKey());
}
}
如果您不喜欢该列表,请在方法内修改。在发布该方法之前,请创建该列表的副本并传递副本而不是原始副本。
List<String> copy = new ArrayList<>(original);
答案 1 :(得分:0)
对于大多数问题,递归是一种可怕的解决方案;包括这个。
尝试非小丑解决方案(假设guava multimap):
Set<String> keySet = multiMap.keySet();
List<String> returnValue = new LinkedList<String>();
for (String currentKey : keySet)
{
Collection<String> values = multiMap.get(currentKey);
returnValue.add(currentKey);
returnValue.addAll(values);
}
答案 2 :(得分:0)
我认为在这种情况下,如果使整个过程更具可读性和/或提供性能优势(更少的内存分配),则使用像list
这样的输入输出参数是合理的。一种“干净”的方法,其中每个getChilds()
调用返回一个新的列表,然后调用者与其他调用组合,这需要额外的内存分配和副本。
另外,如果你坚持使用流,可能是在流上使用mapTo()。reduce():让getChilds()
返回一个新的List,让reduce()将它们全部合并为一个
就个人而言,如果我将getChilds()
作为一个函数编写,我会在这里编写一个正常的循环并手动累积结果:
private static List<String> getChilds(String col, Multimap<String, String> map) {
List<String> list = new ArrayList<>();
list.add(col);
Collection<String> values = map.get(col);
for (String val : values) {
list.addAll(getChilds(val, map);
}
return list;
}
注意:此代码对周期不安全。
但是除了代码风格:@DwB提出了一个好处,即通过将整个地图折叠成单个平面列表,您将丢失有关实际键 - &gt;(值...)关系的所有信息。输出“[P8,P6,P4,P5]”可以由“P8 - >(P6),P4 - >(P5)”或“P8 - >(P6,P4,P5)”产生。 。代码可以更好,但其当前形式的结果实际上有用吗?
答案 3 :(得分:0)
private static List<String> getChilds(String col, Multimap<String, String> map) {
List<String> list = new ArrayList<>();
list.add(col);
map.get(col).forEach(s->list.addAll(getChilds(s, map)));
return list;
}
private static List<String> getList(Multimap<String, String> map) {
Set<String> strings = map.keySet();
List<String> list = new ArrayList<>();
for (String string : strings) {
if (!map.containsValue(string)) {
list.addAll(getChilds(string, map));
}
}
return list;
}
public static void main(String[] args) {
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
map.put("P1", "P2");
map.put("P1", "P3");
map.put("P1", "P4");
map.put("P3", "P5");
map.put("P3", "P6");
map.put("P7", "P8");
map.put("P7", "P9");
map.put("P10", "P1");
System.out.println(getList(map));
}