Преобразование иерархического списка в плоский список в Java - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть иерархическая 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);
  }
}

Ответы [ 4 ]

0 голосов
/ 28 декабря 2018

Сделайте это, используя java-8 flatMap и рекурсию

Измените метод convertToFlatList, чтобы он принимал только один аргумент (i, e 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]
0 голосов
/ 28 декабря 2018

Если вы используете 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 в пустой список:

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());
0 голосов
/ 28 декабря 2018

На самом деле это проблема уровня / рекурсивного обхода дерева.Вот подробности проблемы и решения:

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;
}
0 голосов
/ 28 декабря 2018

Если у Member есть дети, вы правильно добавляете детей в плоский список, но пропускаете сам Member.Просто переместите добавление члена за пределы блока else и добавьте, что с вами все будет в порядке:

private static List<Member> 
convertToFlatList(List<Member> memberList, List<Member> flatList)
{
    for (Member member : memberList)
    {
        // Always add the member to flatList
        flatList.add(memeber);

        // If it has children, add them toore
        if (member.getChildren() != null)
        {
            convertToFlatList(member.getChildren(), flatList);
        }
    }
    return flatList;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...