繁体   English   中英

使用 Streams 模拟嵌套的 for 循环过滤

[英]Simulating nested for-loop filtering using Streams

我正在做一个与口袋妖怪有关的项目。

我有一个PokemonRecord记录,其中有 2 个PokemonTypes的 2 个参数。 PokemonRecord的任何实例都可以有 1 或 2 种类型。 如果PokemonRecord只有 1 种类型,则type2 == null 以下方法的目的是获取一组PokemonTypes并生成所有可能的PokemonRecord类型组合的列表,这些组合将抵抗所有这些给定类型。 将“抵抗类型”视为测试条件并返回boolean的单独方法。

这是预期输出的示例:

Enter the name of a Pokemon type: water
Enter the name of a Pokemon type: ground
Enter the name of a Pokemon type: grass
Enter the name of a Pokemon type: done

The following type combinations resist all of [water, ground, grass]:
Grass
Normal & Grass
Grass & Ice
Grass & Fighting
Grass & Flying
Grass & Psychic
Grass & Bug
Grass & Ghost
Grass & Dragon
Grass & Dark
Grass & Fairy
Flying & Dragon
Bug & Dragon

目前,我的代码按预期工作; 然而,回首往事,我想写一些不同的东西——在国际象棋中,当你找到一个好的棋步时,找到一个更好的棋子。 我最初使用了一种程序化的 for-loop 方法来过滤PokemonTypes的完整列表并测试它们的每一个组合:

public static List<PokemonRecord> genMonResToAll(PokemonTypes... types) {
    List<PokemonTypes> allTypes = //List of possible PokemonTypes that this Pokemon can have (PokemonTypes that are not weak to any inputted PokemonTypes)
    List<PokemonRecord> outputList = new ArrayList<>();

    //Add any single-type Pokemon that resists all types
    for(PokemonTypes type : allTypes)
            if(new PokemonRecord(type).isResistantToAll(types))
                outputList.add(new PokemonRecord(type));

    //Add any multi-type Pokemon that resists all types
    for (int i = 0; i < allTypes.size() - 1; i++)
            for (int j = i + 1; j < allTypes.size(); j++) {
                PokemonRecord testMon = new PokemonRecord(allTypes.get(i), allTypes.get(j));
                if (testMon.isResistantToAll(types))
                    otuputList.add(testMon);
            }
    return outputList;
}

//The functionality of any specific `Pokemon` or `PokemonTypes` method used isn't relevant, they all work as intended.

我现在正在尝试使用Stream API 重写此代码以更具声明性。 我能够弄清楚如何将第一个循环(添加单一类型PokemonRecord的循环)转换为基于 Stream 的声明性语句。 我很难把头绕在第二个周围。 我当前重构第一个循环的代码是:

public static List<PokemonRecord> genMonResToAll(PokemonTypes... types) {
    List<PokemonTypes> allTypes = //List of possible PokemonTypes that this Pokemon can have (PokemonTypes that are not weak to any inputted PokemonTypes)

    //Add any single-type Pokemon that resists all types
    List<PokemonRecord> outputList= allTypes.stream()
    .map(PokemonRecord::new)
    .filter(x -> x.isResistantToAll(types))
    .collect(Collectors.toList());

    //Add any multi-type Pokemon that resists all types
    for (int i = 0; i < allTypes.size() - 1; i++)
            for (int j = i + 1; j < allTypes.size(); j++) {
                PokemonRecord testMon = new PokemonRecord(allTypes.get(i), allTypes.get(j));
                if (testMon.isResistantToAll(types))
                    otuputList.add(testMon);
            }
    return outputList;
}

//The functionality of any specific `Pokemon` or `PokemonTypes` method used isn't relevant, they all work as intended.

由于 PokemonRecord 是二维的,我认为你不应该使用流。 这是没有流的更好方法:

  1. 如果你还没有这样做,这是一个干净的 PokemonRecord 实现,它保证 PokemonRecord(type1, type2) == PokemonRecord(type2, type1)。 以这种方式防止任何非法不相等的对象通常是一个好主意:
public record PokemonRecord(PokemonType type1, PokemonType type2) {
    
    public PokemonRecord(PokemonType type1, PokemonType type2) {
        if (type1 == type2) throw new IllegalArgumentException("Illegal type combination");
        boolean order = type1 != null && (type2 == null || type1.compareTo(type2) < 0);
        this.type1 = order ? type1 : type2;
        this.type2 = order ? type2 : type1;
    }

    // your methods
}
  1. 现在只需将null添加到 allTypes 并对其进行楼梯迭代(以获得所有可能的组合而不重复):
public static List<PokemonRecord> genMonResToAll(PokemonType... types) {
    List<PokemonType> allTypes = new ArrayList<>();
    allTypes.add(null);
    List<PokemonRecord> result = new ArrayList<>();
    for (int s = allTypes.size(), i = 0; i < s; i++) for (int j = s - 1; j > i; j--) {
        PokemonRecord record = new PokemonRecord(allTypes.get(i), allTypes.get(j));
        if (record.isResistantToAll(types)) result.add(record);
    }
    return result;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM