[英]Java : Creating `List` from `Multimap`
I want to arrange values in Multimap
in a ordered List
. 我想将Multimap
中的值排列在有序List
。 Where in all the key will be at the left side and all the values will be at right side. 所有键的位置都在左侧,所有值都在右侧。 I have used recursion to achieve this. 我已经使用递归来实现这一点。 But for that I have to pass List
to that recursive function which returns void
but the List
gets modified in that function which I don't like, is there any way to improve this? 但是,我必须通过List
到返回递归函数void
,但List
获取该功能修改,我不喜欢,有没有什么办法来提高呢?
Following is my example code 以下是我的示例代码
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]
Please suggest if there is any nice way with which I will not break any principle of clean code and still get the desired result. 请提出建议,如果有什么不错的方法,我不会破坏任何干净代码的原则,但仍然会得到所需的结果。
So if we put a new entry in the map like 因此,如果我们在地图中放置一个新条目,例如
map.put("P10", "P1");
then corresponding change in the output would be 那么输出中的相应变化将是
Output : [P7, P8, P9, P10, P1, P2, P3, P5, P6, P4]
All the keys on the left and all the values on the right of the list: 列表左侧的所有键和右侧的所有值:
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());
}
}
If you don't like that list get's modified inside a method. 如果您不喜欢该列表,请在方法内部进行修改。 Before issuing that method create a copy of that list and pass a copy instead of original. 在发出该方法之前,请创建该列表的副本,然后传递副本而不是原始副本。
List<String> copy = new ArrayList<>(original);
Recursion is a terrible solution for most problems; 对于大多数问题,递归是一个糟糕的解决方案。 including this one. 包括这个。
Try a non-clown solution (assuming 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);
}
I think in a case like this, using an in-out parameter like list
could be justified if it makes the overall process more readable, and/or provides performance advantages (fewer memory allocations). 我认为,在这种情况下,如果使用in-out参数(例如list
可以使整个过程更具可读性和/或提供性能优势(减少内存分配),则是合理的。 A 'clean' approach where each getChilds()
call returns a fresh list which the caller then combines with the others, comes at the price of additional memory allocations and copies. 一种“干净”的方法,其中每个getChilds()
调用都返回一个新列表,然后调用方将其与其他调用方合并,以增加内存分配和复制为代价。
The alternative, if you insist on using streams, could maybe be to use mapTo().reduce() on the stream: let getChilds()
return a fresh List, and let reduce() combine them all into one. 如果您坚持使用流,则另一种选择可能是在流上使用mapTo()。reduce():让getChilds()
返回一个新鲜的List,并让reduce()将它们全部合并为一个。
Personally, if I were to write getChilds()
as a function, I'd write a normal loop here and accumulate the results by hand: 就个人而言,如果我将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;
}
Note: This code is not safe against cycles. 注意:此代码对于循环是不安全的。
But code style aside: @DwB raises the good point that by collapsing the whole map into a single flat list, you lose all information about the actual key->(value...) relations. 但是除了代码风格:@DwB带来了一个好处,即通过将整个地图折叠到一个平面列表中,您会丢失有关实际key->(value ...)关系的所有信息。 The output "[ P8, P6, P4, P5]" can be produced by "P8 -> (P6), P4 -> (P5)", or by "P8 -> (P6, P4, P5)". 输出“ [P8,P6,P4,P5]”可以通过“ P8->(P6),P4->(P5)”或“ P8->(P6,P4,P5)”生成。 The code can be made nicer, but is the result in its current form actually useful? 可以使代码更好,但是以当前形式显示的结果实际上有用吗?
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));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.