【问题标题】:Stringbuilder to Array to 2D Array causing NullPointerException JAVA [closed]Stringbuilder 到 Array 到 2D Array 导致 NullPointerException JAVA [关闭]
【发布时间】:2021-07-06 23:02:18
【问题描述】:

我有一种将 .txt 文件读入二维数组的方法,该 txt 文件包含带有“Y”或“N”的行以及 1-24 之间的团队编号(行看起来像“T# Y”或“ T# N”,然后我在该二维数组中搜索行中的特定元素(“Y”)并返回有多少行有“Y”,并为每个团队计算真实案例的数量。

24 个团队,我认为至少应该是 2d 数组中的 24 行!

public static String[][] buildTimes(String[][] sub) {
    StringBuilder scores = new StringBuilder(sub.length);

    for (String[] row : sub) {
        scores.append(Arrays.stream(row)
                .filter(str -> str.equalsIgnoreCase("Y"))
                .toArray().length);
        scores.append("/");
    }

    String[] tempArray = scores.toString().split("");
    String[][] finalTimes = new String[24][1];

    for (int i = 0; i < finalTimes.length; i++) {
        for (int j = 0; j < finalTimes[i].length; j++) {
            int index = 0;
            finalTimes[i][j] = tempArray[index];
            index++;
        }
    }
    return finalTimes;
}

我收到错误:

Exception in thread "main" java.lang.NullPointerException
    at test.lambda$buildTimes$0(test.java:74)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:176)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:550)
    at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
    at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:517)
    at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:523)
    at test.buildTimes(test.java:74)
    at run.main(run.java:10)

我不知道为什么会出现这些错误,我绝对没有使用 StringBuilders 的经验,我也尝试过使用 INT ArrayList 和相同的错误。

输出示例: Team 1(为 Team1 找到的 Y 计数) 团队 2(“”代表团队 2) 第 3 队(第 3 队的“”)

我只需要一个包含 Team# 的 2D 数组,并且在第 1 列到第 24 列的文件中的行中为每个团队找到“Y”。

【问题讨论】:

    标签: java arrays arraylist multidimensional-array stringbuilder


    【解决方案1】:

    您可以轻松解决问题:

    public static void main(String[] args) {
        String[][] a = {{"T1", "Y"}, {"T1", "Y"}, {"T2", "N"}, {"T2", "Y"}};
        System.out.println(buildTimes(a)); // {T1=2, T2=1}
    }
    
    public static Map<String, Long> buildTimes(String[][] data){
        return Stream.of(data)
                .filter(item -> item.length > 1)
                .filter(item -> "y".equalsIgnoreCase(item[1]))
                .map(item -> item[0])
                .collect(groupingBy(item -> item, Collectors.counting()));
    }
    

    【讨论】:

    • testJava(67108964) 类型的 groupingBy(( item) -> {}, Collectors.counting()) 方法未定义,几乎可以工作,只是现在说。我还需要将此数据移动到二维数组中
    【解决方案2】:

    只要问题中已经使用了 Stream API,最好使用它的工具来计算元素的频率,使用 Collectors::groupingBy 而不是 StringBuilder。如果将频率计为Integer 很重要,则可以使用Collectors::summingInt 而不是Collectors::counting 返回Long

    可以使用IntStream::rangeIntStream::rangeClosed 生成为每个团队返回一个稀疏数组的最终结果(包括输入文件中缺少的那些)

    实现可以如下:

    public static String[][] countYesPerTeam(String[][] data) {
        Map<String, Integer> map = Arrays.stream(data)
                .filter(item -> item.length > 1 && "Y".equalsIgnoreCase(item[1]))
                .collect(Collectors.groupingBy(item -> item[0], Collectors.summingInt(item -> 1)));
        
        return IntStream.rangeClosed(1, 24)
                        .mapToObj(i -> new String[] {
                            "T" + i, 
                            Integer.toString(map.getOrDefault("T" + i, 0))
                        }) // provide [TN, yesCount] per team
                        .toArray(String[][]::new);
    }
    
    

    测试

    String[][] data = {{"T1", "Y"}, {"T2", "Y"}, {"T1", "N"}, {"T2", "Y"}, {"T4", "y"}};
    String[][] stat = countYesPerTeam(data);
    System.out.println(Arrays.deepToString(stat));
    

    输出:

    [[T1, 1], [T2, 2], [T3, 0], [T4, 1], [T5, 0], [T6, 0], [T7, 0], [T8, 0], [T9, 0], [T10, 0], [T11, 0], [T12, 0], [T13, 0], [T14, 0], [T15, 0], [T16, 0], [T17, 0], [T18, 0], [T19, 0], [T20, 0], [T21, 0], [T22, 0], [T23, 0], [T24, 0]]
    

    如果结果数组中不需要团队名称,则可以将其创建为:

    // ....
        return IntStream.rangeClosed(1, 24)
                        .mapToObj(i -> new String[] {
                            Integer.toString(map.getOrDefault("T" + i, 0))
                        }) // provide [yesCount] per team
                        .toArray(String[][]::new);
    

    【讨论】:

    • 这几乎可以完美运行,但是对于每个 Y 的团队得分,我只得到 0。
    • 您能否提供一个输入到方法countYesPerTeams 中的二维数组的简短示例?当前实现假定每一行的格式为{"Tx", "Y|N"},其中Txrow[0] 中的团队编号,row[1] 包含YN。这个假设是由以下语句做出的:行看起来像“T# Y”或“T# N”,所以当一行被" " 分割时,会返回上述格式的数组.
    猜你喜欢
    • 1970-01-01
    • 2018-08-25
    • 2022-12-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多