结合列表子集,Java生成列表

时间:2019-05-12 02:23:50

标签: java list java-8 subset combinations

这个问题将用Java实现。

我有一个名为Competitor的类,具有类型,名称和功能。

public class Competitor {
  private final int type;
  private final String name;
  private final int power;

  public Competitor(int type, String name, int power) {
    this.type = type;
    this.name = name;
    this.power = power;
  }

  public int getType() {
    return type;
  }

  public String getName() {
    return name;
  }

  public int getPower() {
    return power;
  }

  @Override
  public String toString() {
    return "Competitor{" + "type=" + type + ", name=" + name + ", power=" + power + '}';
  }

}

现在,我想做一个游戏,type有一个竞争对手,类型的数量可以是60(3D arrays或嵌套的for对我来说不是解决方案)

我想生成此列表的子集(按类型分类)的所有可能组合。

public class Game {
  public static void main(String... args) {
    List<Competitor> listCompetitors = new ArrayList<>();
    listCompetitors.add(new Competitor(1, "Cat 00", 93));
    listCompetitors.add(new Competitor(1, "Cat 10", 11));
    listCompetitors.add(new Competitor(1, "Cat 23", 20));

    listCompetitors.add(new Competitor(2, "Dog 61", 54));
    listCompetitors.add(new Competitor(2, "Dog 18", 40));
    listCompetitors.add(new Competitor(2, "Dog 45", 71));
    listCompetitors.add(new Competitor(2, "Dog 30", 68));

    listCompetitors.add(new Competitor(3, "Pig 90", 90));
    listCompetitors.add(new Competitor(3, "Pig 78", 32));

    listCompetitors.add(new Competitor(4, "Cow 99", 90));

    // The type is NOT fixed number (is variable from 1 to 60)
  }
}

如何生成类似...的组合

new Competitor(1, "Cat 00", 93)
new Competitor(2, "Dog 61", 54)
new Competitor(3, "Pig 90", 90)
new Competitor(4, "Cow 99", 90)

另一种组合

new Competitor(1, "Cat 00", 93)
new Competitor(2, "Dog 61", 54)
new Competitor(3, "Pig 78", 32)
new Competitor(4, "Cow 99", 90)

...

最后一个组合

new Competitor(1, "Cat 23", 20)
new Competitor(2, "Dog 30", 68)
new Competitor(3, "Pig 78", 32)
new Competitor(4, "Cow 99", 90)

如何像以前建议的那样生成子列表?

我也下注。

考虑功率参数。 List<Competitor>的性能(最低和)和最佳(最大参数)是什么?

2 个答案:

答案 0 :(得分:1)

我相信可以解决问题

public class Game {

  public static void main(String... args) {
    List<Competitor> listCompetitors = new ArrayList<>();

    listCompetitors.add(new Competitor(1, "Cat 00", 93));
    listCompetitors.add(new Competitor(1, "Cat 10", 11));
    listCompetitors.add(new Competitor(1, "Cat 23", 20));

    listCompetitors.add(new Competitor(2, "Dog 61", 54));
    listCompetitors.add(new Competitor(2, "Dog 18", 40));
    listCompetitors.add(new Competitor(2, "Dog 45", 71));
    listCompetitors.add(new Competitor(2, "Dog 30", 68));

    listCompetitors.add(new Competitor(3, "Pig 90", 90));
    listCompetitors.add(new Competitor(3, "Pig 78", 32));

    listCompetitors.add(new Competitor(4, "Cow 99", 90));

    List<Integer> typeList = new ArrayList<>(listCompetitors.stream()
        .map(Competitor::getType)
        .collect(Collectors.toSet()));
    int sizeLimit = typeList.size();

    List<List<Competitor>> listOfListCompetitor = new ArrayList<>();
    getListCompetitorCombination(new ArrayList<>(), listCompetitors, sizeLimit, listOfListCompetitor);

    listOfListCompetitor.stream().forEach(listCompetitor -> {
      System.out.println("");
      listCompetitor.stream().sorted(Comparator.comparing(Competitor::getType)).forEach(System.out::print);
    });
    System.out.println();

  }

  public static List<Competitor> getListCompetitorCombination(List<Competitor> processed, List<Competitor> sublistCompetitor, int sizeLimit, List<List<Competitor>> outCompetitor) {
    List<Competitor> listCompetitorCombination = new ArrayList<>();

    /*
    List<Integer> typeList = new ArrayList<>(sublistCompetitor.stream()
        .map(Competitor::getType)
        .collect(Collectors.toSet()));
    */
    int type = sublistCompetitor.get(0).getType();//typeList.stream().findFirst().orElse(0);

    List<Competitor> listCompetitorsIncludeType = sublistCompetitor
        .stream()
        .filter(competitor -> competitor.getType() == type)
        .collect(Collectors.toList());

    List<Competitor> listCompetitorsExcludeType = sublistCompetitor
        .stream()
        .filter(competitor -> competitor.getType() != type)
        .collect(Collectors.toList());

    listCompetitorsIncludeType.stream().forEach(
        competitor
        -> {

      List<Competitor> newProcessed = new ArrayList<>(processed);
      newProcessed.add(0, competitor);
      if (sizeLimit == newProcessed.size()) {
        outCompetitor.add(newProcessed);
      } else {
        getListCompetitorCombination(newProcessed, listCompetitorsExcludeType, sizeLimit, outCompetitor);
      }
    });
    return listCompetitorCombination;
  }

}

我的输出

    debug:

    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 00, power=93} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 10, power=11} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 61, power=54} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 18, power=40} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 45, power=71} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 90, power=90} Competitor{type=4, name=Cow 99, power=90} 
    Competitor{type=1, name=Cat 23, power=20} Competitor{type=2, name=Dog 30, power=68} Competitor{type=3, name=Pig 78, power=32} Competitor{type=4, name=Cow 99, power=90} 
    BUILD SUCCESSFUL (total time: 1 second)

现在,有人可以提出另一个优化的解决方案吗?

答案 1 :(得分:1)

首先,按类型对所有元素进行分组,以获取要合并的列表。

Map<Integer, List<Competitor>> map
    = listCompetitors.stream().collect(Collectors.groupingBy(Competitor::getType));

然后,要构建笛卡尔乘积,我们需要一个帮助器方法来从现有List和其他元素中创建一个新的List。不幸的是,没有内置的方法(但是您可能会在第三方库中找到此类操作)

static <T> List<T> listWith(List<T> list, T t) {
    List<T> result = new ArrayList<>(list.size() + 1);
    result.addAll(list);
    result.add(t);
    return result;
}

这样,我们可以构造一个Stream并将其收集到结果List中:

Stream<List<Competitor>> stream = Stream.of(Collections.emptyList());
for(List<Competitor> next: map.values())
    stream = stream.flatMap(list -> next.stream().map(c -> listWith(list, c)));

List<List<Competitor>> listOfListCompetitor = stream.collect(Collectors.toList());

每个flatMap步骤将流与另一个维度合并。

listWith的收集操作也可以通过另一个流操作来完成,例如

Stream<List<Competitor>> stream = Stream.of(Collections.emptyList());
for(List<Competitor> next: map.values())
    stream = stream.flatMap(list -> next.stream()
        .map(c -> Stream.concat(list.stream(), Stream.of(c)).collect(Collectors.toList())));

List<List<Competitor>> listOfListCompetitor = stream.collect(Collectors.toList());

但这不是那么直观,恕我直言。