Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用streams从字符串[]中创建字符串[],索引作为值的一部分_Java_Arrays_Java Stream - Fatal编程技术网

Java 使用streams从字符串[]中创建字符串[],索引作为值的一部分

Java 使用streams从字符串[]中创建字符串[],索引作为值的一部分,java,arrays,java-stream,Java,Arrays,Java Stream,我有一个String[],其中的值需要放入String[][]中,每个“行”由当前索引和前一个数组的值组成。迭代解决方案如下所示: String[] vals = getValsFromSomewhere(); String[][] targetArray = new String[vals.length][]; for (int i = 0; i < targetArray.length; i++) { targetArray[i] = new String[]{

我有一个
String[]
,其中的值需要放入
String[][]
中,每个“行”由当前索引和前一个数组的值组成。迭代解决方案如下所示:

String[] vals = getValsFromSomewhere();
String[][] targetArray = new String[vals.length][];
for (int i = 0; i < targetArray.length; i++) {
    targetArray[i] = new String[]{
        Integer.toString(i), vals[i]
    };
}

这是一个流的解决方案,好吧。但我最初的部分目标,即去掉临时变量(
vals
,在本例中),并没有实现。在
Stream
中搜索可用的方法并没有找到任何有用的东西,但我可能遗漏了一些东西。这就是我在这里提问的原因;-)非常感谢为我指出正确的方向。

删除临时变量VAL意味着您无法知道在创建流之前要处理多少个元素,因此无法使用range()。我看不出如何消除所有临时变量,但作为替代方案,我引入了一个AtomicInteger,它在流处理中递增以支持索引

我当然不是说这是一种比你更好的方法,我很感兴趣的是,除了range()AtomicInteger(仅使用标准Java)之外,是否还有其他方法用于流索引

代码如下:

String[] getValsFromSomewhere() {

    return new String[]{"The", "rain", "in", "Spain", "stays", "mainly", "in", "the", "plain!"};
}

void test() {

    AtomicInteger ai = new AtomicInteger(0);

    String[][] target = Stream.of(getValsFromSomewhere())
                              .map(e -> new String[]{e, String.valueOf(ai.getAndIncrement())})
                              .toArray(String[][]::new);

    for(int row=0; row<target.length; row++) {
        for(int element=0; element<target[row].length; element++) {
            System.out.println("target[" + row +"] [" + element + "] = " + target[row][element]);
        }
    }    
}
String[]getValsFromSomewhere(){
返回新字符串[]{“The”,“rain”,“in”,“西班牙”,“stays”,“main”,“in”,“The”,“plain!”;
}
无效测试(){
AtomicInteger ai=新的AtomicInteger(0);
字符串[][]目标=Stream.of(getValsFromSomewhere())
.map(e->newstring[]{e,String.valueOf(ai.getAndIncrement())})
.toArray(字符串[]:[]::新建);

对于(int row=0;row为什么不编写您自己的
收集器(或者更好地说,让我为您编写一个)?似乎有点过分,但这就是您可以使用的:

class Array2DCollector implements Collector<String, Map<Integer,String>, String[][]>{

    private final AtomicInteger index = new AtomicInteger(0);

    @Override
    public Supplier<Map<Integer, String>> supplier(){
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<Integer, String>, String> accumulator(){
        return (map, string) -> map.put(index.getAndIncrement(), string);
    }

    @Override
    public BinaryOperator<Map<Integer, String>> combiner(){
        return (map1, map2) -> {
            map1.putAll(map2);
            return map1;
        };
    }

    @Override
    public Function<Map<Integer, String>, String[][]> finisher(){
        return map -> {
            final String[][] array = new String[index.get()][2];
            for(int i = 0; i < map.size(); i++){
                array[i][0] = String.valueOf(i);
                array[i][1] = map.get(i);
            }
            return array;
        };
    }

    @Override
    public Set<Characteristics> characteristics(){
        return EnumSet.noneOf(Characteristics.class);
    }
}
解释:简言之,收集器有一个内部变量
index
,该变量仅用于计数。对于流中的每个元素,该变量都会增加,元素会保存在hashMap中。最后,hashMap会转换为2D数组

重要注意事项:此收集器基于
HashMap
,不能同时执行,并且是有序的


最后一点提示:如前所述,这有点过分,但为什么不试试呢;)

你做对了,没有遗漏任何东西。但是,说真的,为什么不使用字符串数组来存储整数和字符串?为什么不使用具有两个正确类型属性的类?因为这是后续API调用所需的参数。哦,我的天哪。@jbnize不是真的,而且专用cla也会有同样的问题ss,因为您仍然需要设置相应的值。感谢您的想法。您通过引入一个新的临时变量消除了一个临时变量,因此我仍然处于与以前相同的情况(即:在不需要临时变量的地方使用临时变量)我不想在Dailywtf;-)@Lothar上出现,我知道你不需要任何临时变量,但不管你是否“不需要它们”是另一个问题。我怀疑对于您的需求,临时变量可能是必要的,但我很高兴被证明是错误的。您的实现工作正常,但创建一个仅用于顺序流的收集器并不好,因为没有什么可以阻止调用方将该收集器与并行流一起使用。To解决该问题,从组合器()中删除代码方法,并返回null。处理顺序流仍然可以工作,但处理并行流将因NullPointerException而失败,这比可能无误返回垃圾结果要好得多。@skomisa您得到了一个点,但为什么不直接抛出,这样您就可以给出一个明确的错误,而不是返回null这种方法的问题是,您不能假设不会为顺序流调用combiner()方法,对于您的代码,它就是。(向combiner()添加println()以验证您自己。)因此如果combiner()盲目地抛出一个异常,它将破坏顺序流和并行流。看起来您的组合器()返回的值在处理顺序流时被丢弃。请参阅,但更重要的一点是,如果代码涉及到流是顺序流还是并行流,那么整个方法可能需要重新考虑。谢谢。我将尝试一下,我想我会学到一些关于流的新知识;-)
class Array2DCollector implements Collector<String, Map<Integer,String>, String[][]>{

    private final AtomicInteger index = new AtomicInteger(0);

    @Override
    public Supplier<Map<Integer, String>> supplier(){
        return HashMap::new;
    }

    @Override
    public BiConsumer<Map<Integer, String>, String> accumulator(){
        return (map, string) -> map.put(index.getAndIncrement(), string);
    }

    @Override
    public BinaryOperator<Map<Integer, String>> combiner(){
        return (map1, map2) -> {
            map1.putAll(map2);
            return map1;
        };
    }

    @Override
    public Function<Map<Integer, String>, String[][]> finisher(){
        return map -> {
            final String[][] array = new String[index.get()][2];
            for(int i = 0; i < map.size(); i++){
                array[i][0] = String.valueOf(i);
                array[i][1] = map.get(i);
            }
            return array;
        };
    }

    @Override
    public Set<Characteristics> characteristics(){
        return EnumSet.noneOf(Characteristics.class);
    }
}
final String[][] target = Arrays.stream(vals).collect(new Array2DCollector());