我有一个类似下面的层次结构list
,我想将其转换为平面list
。
我写了一种叫做convertToFlatList
的方法,并使用了它。但是最终结果中缺少一些要素。我做错了什么?
还有比我过去将列表转换为平面列表更好的方法吗?
我添加了示例代码和类似于我在场景中必须使用的对象的东西。最终结果应该是1、2、3、4、5、6、7
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main
{
public static void main(String[] args)
{
Member memberOne = new Member(1);
Member memberTwo = new Member(2);
Member memberThree = new Member(3);
Member memberFour = new Member(4);
Member memberFive = new Member(5);
Member memberSix = new Member(6);
Member memberSeven = new Member(7);
memberTwo.setChildren(Arrays.asList(memberThree, memberFour));
memberFour.setChildren(Arrays.asList(memberFive, memberSix));
List<Member> memberList = Arrays.asList(memberOne, memberTwo, memberSeven);
List<Member> flatList = new ArrayList<>();
List<Member> convertedList = convertToFlatList(memberList, flatList);
System.out.println(convertedList);
}
private static List<Member> convertToFlatList(List<Member> memberList, List<Member> flatList)
{
for (Member member : memberList)
{
if (member.getChildren() != null)
{
convertToFlatList(member.getChildren(), flatList);
}
else
{
flatList.add(member);
}
}
return flatList;
}
}
class Member
{
private List<Member> children;
private int memberId;
Member(int memberId)
{
this.memberId = memberId;
}
List<Member> getChildren()
{
return children;
}
void setChildren(List<Member> children)
{
this.children = children;
}
int getMemberId()
{
return memberId;
}
void setMemberId(int memberId)
{
this.memberId = memberId;
}
@Override
public String toString()
{
return String.valueOf(this.memberId);
}
}
答案 0 :(得分:7)
如果lib
有子级,则可以将子级正确添加到扁平化列表中,但是会错过Member
本身。只需将成员的添加移到Member
块添加之外,就可以了:
else
答案 1 :(得分:6)
如果您使用Java 8,只需将此方法添加到Member
类中即可:
public Stream<Member> streamAll(){
if(getChildren() == null){
return Stream.of(this);
}
return Stream.concat(Stream.of(this), getChildren().stream().flatMap(Member::streamAll));
}
或者,如果您始终将children
初始化为空列表,则可以删除null检查:
public Stream<Member> streamAll(){
return Stream.concat(Stream.of(this), getChildren().stream().flatMap(Member::streamAll));
}
然后获取平面列表:
List<Member> convertedList = memberList.stream()
.flatMap(Member::streamAll)
.collect(Collectors.toList());
答案 2 :(得分:2)
使用java-8 flatMap
和递归来实现
将
convertToFlatList
方法更改为仅接受一个参数(即List<Member>
)
如果getChildren()
不是null
,则进行递归或返回当前对象
private static List<Member> convertToFlatList(List<Member> memberList)
{
return memberList.stream().flatMap(i->{
if(Objects.nonNull(i.getChildren())) {
return Stream.concat(Stream.of(i), convertToFlatList(i.getChildren()).stream());
}
return Stream.of(i);
}).collect(Collectors.toList());
}
输出:
[1, 2, 3, 4, 5, 6, 7]
答案 3 :(得分:1)
实际上,这是树的级别/递归顺序遍历的问题。这里是问题的详细信息和解决方案:
https://en.wikipedia.org/wiki/Tree_traversal
顺便说一下,这是问题的遍历(深度优先顺序):
static class Member {
List<Member> children = new ArrayList<>();
int id;
boolean visit = false;
}
public List<Member> printList(Member member) {
Stack<Member> stack = new Stack<>();
List<Member> list = new ArrayList<>();
stack.push(member);
while(!stack.isEmpty()) {
Member node = stack.pop();
list.add(node);
for(Member m: node.children) {
stack.push(m);
}
}
return list;
}