标签: java-stream

合并两个流

我试图实现一个方法来合并两个Streams中的值基于a Comparator的值.

我有办法做到这一点,我迭代流并将值插入到一个Stream.Builder,但我还没有弄清楚如何制作一个懒惰评估版本(许多流操作的方式),所以它可以处理无限流.

我想要它做的就是对输入数据执行单个合并传递,而不是对流进行排序(实际上,流很可能是无序的;需要保留这种混乱).

static Stream<E> merge(Stream<E> first, Stream<E> second, Comparator<E> c)
Run Code Online (Sandbox Code Playgroud)

我如何懒惰地合并这样的两个流?

如果我用两个Queues作为输入,一些Consumer作为输出,这将是相当简单的:

void merge(Queue<E> first, Queue<E> second, Consumer<E> out, Comparator<E> c){
    while(!first.isEmpty() && !second.isEmpty()
        if(c.compare(first.peek(), second.peek()) <= 0)
            out.accept(first.remove());
        else
            out.accept(second.remove());
    for(E e:first)
        out.accept(e);
    for(E e:second)
        out.accept(e);
}
Run Code Online (Sandbox Code Playgroud)

但我需要使用惰性评估和流来完成这项工作.

为了解决这些评论,这里有一些示例输入和结果:

例1:

merge(
    Stream.of(1, 2, 3, 1, 2, 3),
    Stream.of(2, 2, 3, 2, 2, 2),
    Comparator.naturalOrder()
);
Run Code Online (Sandbox Code Playgroud)

将返回一个将产生此序列的流:

1, 2, 2, 2, 3, 3, 1, 2, …
Run Code Online (Sandbox Code Playgroud)

java merge java-8 java-stream

10
推荐指数
1
解决办法
7665
查看次数

字符串数组上的Java 8流

我有一个格式的字符串:

row1col1 row1col2
row2col1 row2col2
row3col1 row3col2
Run Code Online (Sandbox Code Playgroud)

等等...

我想提取每个项目并构建一个具有以下属性的对象数组:

new MyObject(row1col1, row1col2); 
Run Code Online (Sandbox Code Playgroud)

我是Java 8和Streams的新手,我想知道如何在没有循环的情况下实现这一点.

通常我会使用a String.split('\n')将行累积到String数组中

然后是一个循环,我将在空格分隔符上再次分割每一行,并使用两个元素的结果数组(row1col1 row1col2)构建我的对象,直到没有更多行要处理.

像这样:

String sausage = "row1col1 row1col2\nrow2col1 row2col2\nrow3col1 row3col2";
String[] rows = sausage.split("\n");

for (String row : rows) {
    String[] objectData = u.split("\\s+");
    MyObject myObject = new MyObject(objectData[0], objectData[1]);
    myObjectList.add(myObject);
}
Run Code Online (Sandbox Code Playgroud)

谁能解释我如何用流来实现同样的目标,那背后的机制是什么让我这样做呢?

在增加元素数量时,这甚至是一种有效的思维方式,因为从我看到的所有示例中,流程都集中在过滤,收集或通常给出一组元素检索应用一些标准的次要集合.

java arrays collections java-8 java-stream

10
推荐指数
2
解决办法
2万
查看次数

如何在Stream链中调用setter

如何在不使用forEach()的情况下调用Stream链中的setter?

List<Foo> newFoos = foos.stream()
        .filter(foo -> Foo::isBlue)
        .map(foo -> foo.setTitle("Some value")) //I am unable to use this because also changing the data type into Object
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

10
推荐指数
3
解决办法
6668
查看次数

Java 8获取列表中的所有元素

我有一个对象列表,其中每个对象返回List<String>.如何使用Java 8流只获取一个List<String>?

Contact class有以下方法;

public List<String> getSharedFriendsIds() {
    return sharedFriendsIds;
}
Run Code Online (Sandbox Code Playgroud)

我有

List<Contact> contactsList;
Run Code Online (Sandbox Code Playgroud)

我在想的是

List<String> sharedContacts = contactsList.stream()
    .map(Contact::getSharedFriendsIds)
    .sequential()
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但上面的线不是返回 List<String>,而是 List<List<String>>我不想要的.

java java-8 java-stream

10
推荐指数
2
解决办法
2万
查看次数

查看流中的下一个元素

有没有办法窥视流中的下一个元素?这个想法来自一个对象列表的流,其中应该比较两个跟随的对象(以平滑一些差异,但这在这里不重要).作为一个旧for循环,这看起来像:

List<Car> autobahn = getCars();
for (int i = 0; i < autobahn.size()-1; i++) {
    if(autobahn.get(i).speed>autobahn.get(i+1).speed)
        autobahn.get(i).honk();
}
Run Code Online (Sandbox Code Playgroud)

到目前为止流的最佳方式是:

autobahn.stream()
            .limit(autobahn.size()-1)
            .filter(car -> car.speed < autobahn.get(autobahn.indexOf(car)+1).speed)
            .forEach(car -> car.honk());
Run Code Online (Sandbox Code Playgroud)

这个解决方案的主要问题是indexOf方法,因为高速公路上可能有两倍于同一辆车.一个更好的解决方案是某种方式来窥视下一个(或前一个)元素(有一个帮助类,这可能是可能的,但看起来很可怕)

BoxedCar boxedCar = new BoxedCar(autobahn.get(0));
autobahn.stream()
            .skip(1)
            .filter(car -> boxedCar.setContent(car))
            .forEach(car -> car.winTheRace());
Run Code Online (Sandbox Code Playgroud)

与助手类

class BoxedCar {

    Car content;

    BoxedCar(Car content) {
        this.content = content;
    }
    boolean setContent(Car content) {
        double speed = this.content.speed;
        this.content = content;
        return content.speed > speed;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者转移Stream<Car>到 …

java java-stream

10
推荐指数
1
解决办法
3255
查看次数

使用java 8流将String替换为hashmap值

我String和HashMap像下面的代码:

Map<String, String> map = new HashMap<>();
    map.put("ABC", "123");
    String test = "helloABC";
    map.forEach((key, value) -> {
        test = test.replaceAll(key, value);
    });
Run Code Online (Sandbox Code Playgroud)

我尝试用HashMap值替换字符串,但这不起作用,因为test是最终的,不能在正文中重新分配forEach.

那么,有没有任何解决方案,以取代String与HashMap使用Java 8个流API?

java hashmap java-8 java-stream

10
推荐指数
1
解决办法
4483
查看次数

为什么Java Stream生成器无序?

我尝试将一些工作与Java Streams并行化.让我们考虑一下这个简单的例子:

Stream.generate(new Supplier<Integer>() {
        @Override
        public Integer get() {
            return generateNewInteger();
        }
    })
    .parallel()
    .forEachOrdered(new Consumer<Integer>() {
        @Override
        public void accept(Integer integer) {
            System.out.println(integer);
        }
    });
Run Code Online (Sandbox Code Playgroud)

问题是它没有调用accept方法forEachOrdered,它只在我使用时才有效forEach.我想问题是Stream.generate内部创造的InfiniteSupplyingSpliterator没有ORDERED特征.

问题是为什么?看起来我们知道数据的生成顺序.第二个问题是如何forEachOrdered在生成流元素的情况下对并行化流进行操作?

java java-stream

10
推荐指数
1
解决办法
337
查看次数

带有instanceof和类cast的方法引用的Java流

我可以使用方法参考转换以下代码吗?

List<Text> childrenToRemove = new ArrayList<>();

group.getChildren().stream()
    .filter(c -> c instanceof Text)
    .forEach(c -> childrenToRemove.add((Text)c));
Run Code Online (Sandbox Code Playgroud)

让我举一个例子来说明我的意思,假设我们有

myList
    .stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(elem -> System.out.println(elem));
Run Code Online (Sandbox Code Playgroud)

使用方法引用它可以写成(最后一行)

myList
    .stream()
    .filter(s -> s.startsWith("c"))
    .map(String::toUpperCase)
    .sorted()
    .forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

将表达式转换为方法引用的规则是什么?

java java-8 java-stream method-reference

10
推荐指数
1
解决办法
6471
查看次数

Java Stream Grouping可以收集自定义对象

我有温度等级

class Temperature {
    double minTemp;
    double maxTemp;
    String city;
    String country;
}
Run Code Online (Sandbox Code Playgroud)

我有另一个维护温度集合的类

class Temperatures {
    List<Temperature> temperatures;
}
Run Code Online (Sandbox Code Playgroud)

我想使用streams对countryName进行分组.

我想要的是

public Map<String, Temperatures> temperaturesByCountry()
Run Code Online (Sandbox Code Playgroud)

但我无法使用流将温度作为地图值,我得到的是温度列表.

我的分组实现如下

Map<String, List<Temperature>> result = this.getTemperatures()
                .stream()
                .collect(Collectors.groupingBy(Temperature::getCountry));
Run Code Online (Sandbox Code Playgroud)

我想要Map<String, Temperatures>而不是Map<String, List<Temperature>>

我怎样才能做到这一点.

java grouping hashmap java-8 java-stream

10
推荐指数
1
解决办法
695
查看次数

在带有流的List中找到与目标相距n步的值

假设我有一个简单的列表:

List<String> listOne = Arrays.asList("str1", "result1", "test", "str4", "result2", "test", "str7", "str8");
Run Code Online (Sandbox Code Playgroud)

目标是"测试",我想将目标之前的值添加到新列表中,因此输出将是[result1, result2].

使用类似的东西添加"测试"值很容易,listTwo = listOne.stream().filter(i -> i.equals("test")).collect(Collectors.toList());但是如何根据目标的位置获取其他值(在我的示例中,它只是目标之前的元素)

我试着只是改变了i到i - 1但没有采取任何行动.

我知道我可以用一个简单的for循环来做,但只是想知道如何在流中应用相同的逻辑.

for (int i = 1; i < listOne.size(); i++) {
    if (listOne.get(i).equals("test")) {
        listTwo.add(listOne.get(i - 1));
    }
}
Run Code Online (Sandbox Code Playgroud)

java java-stream

10
推荐指数
2
解决办法
99
查看次数