我试图实现一个方法来合并两个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) 我有一个格式的字符串:
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)
谁能解释我如何用流来实现同样的目标,那背后的机制是什么让我这样做呢?
在增加元素数量时,这甚至是一种有效的思维方式,因为从我看到的所有示例中,流程都集中在过滤,收集或通常给出一组元素检索应用一些标准的次要集合.
如何在不使用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) 我有一个对象列表,其中每个对象返回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>>我不想要的.
有没有办法窥视流中的下一个元素?这个想法来自一个对象列表的流,其中应该比较两个跟随的对象(以平滑一些差异,但这在这里不重要).作为一个旧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>到 …
我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 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在生成流元素的情况下对并行化流进行操作?
我可以使用方法参考转换以下代码吗?
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)
将表达式转换为方法引用的规则是什么?
我有温度等级
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>>
我怎样才能做到这一点.
假设我有一个简单的列表:
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)