最近我更改了JDK 8的版本而不是我的项目中的7个,现在我使用Java 8附带的新功能覆盖了一些代码片段.
final Matcher mtr = Pattern.compile(regex).matcher(input);
HashSet<String> set = new HashSet<String>() {{
while (mtr.find()) add(mtr.group().toLowerCase());
}};
Run Code Online (Sandbox Code Playgroud)
我如何使用Stream API编写此代码?
如何计算流过滤器的匹配?我正在尝试将以下代码重构为java8 stream:
//java7
int i = 0;
for (Node node : response.getNodes()) {
Integer id = node.getId();
if (id != null) {
node.setContent("This is the id: " + id);
i++;
}
}
//java8
response.getNodes().stream()
.filter(node -> node.getId() != null)
.forEach(node -> node.setValue("This is the id: " + node.getId()));
Run Code Online (Sandbox Code Playgroud)
我现在如何获得已应用的已过滤元素的数量?Sidequestion:在旧代码中我可以Integer id多次重复使用.如何使用流实现相同的功能?
假设我有两个int[]数组input1和input2.我想从第一个中取正数,从第二个中取出不同的数字,将它们合并在一起,排序并存储到结果数组中.这可以使用流执行:
int[] result = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
我想加快任务,所以我考虑使流并行.通常这只意味着我可以.parallel()在流构造和终端操作之间插入任何地方,结果将是相同的.IntDream.concat的JavaDoc 表示如果任何输入流是并行的,则生成的流将是并行的.所以,我认为做parallel()任何input1流或input2流或级联的流将产生相同的结果.
实际上我错了:如果我添加.parallel()到结果流,似乎输入流保持顺序.此外,我可以将输入流(它们中的任何一个或两者)标记为.parallel(),然后将结果流转换为.sequential(),但输入保持平行.所以实际上有8种可能性:input1,input2和连接流都可以是并行的:
int[] sss = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
int[] ssp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).parallel().sorted().toArray();
int[] sps = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sequential().sorted().toArray();
int[] spp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sorted().toArray();
int[] pss = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).distinct()).sequential().sorted().toArray(); …Run Code Online (Sandbox Code Playgroud) 将流转换为滑动窗口的推荐方法是什么?
例如,在Ruby中你可以使用each_cons:
irb(main):020:0> [1,2,3,4].each_cons(2) { |x| puts x.inspect }
[1, 2]
[2, 3]
[3, 4]
=> nil
irb(main):021:0> [1,2,3,4].each_cons(3) { |x| puts x.inspect }
[1, 2, 3]
[2, 3, 4]
=> nil
Run Code Online (Sandbox Code Playgroud)
在Guava中,我发现只有Iterators#partition,它是相关的但没有滑动窗口:
final Iterator<List<Integer>> partition =
Iterators.partition(IntStream.range(1, 5).iterator(), 3);
partition.forEachRemaining(System.out::println);
-->
[1, 2, 3]
[4]
Run Code Online (Sandbox Code Playgroud) 我想用Java 8编写纯函数,将集合作为参数,对该集合的每个对象应用一些更改,并在更新后返回一个新集合.我想遵循FP原则,所以我不想更新/修改作为参数传递的集合.
有没有办法使用Stream API而不先创建原始集合的副本(然后使用forEach或'normal'for循环)?
下面的示例对象,并假设我想将文本追加到其中一个对象属性:
public class SampleDTO {
private String text;
}
Run Code Online (Sandbox Code Playgroud)
所以我想做类似下面的事情,但不修改集合.假设"列表"是一个List<SampleDTO>.
list.forEach(s -> {
s.setText(s.getText()+"xxx");
});
Run Code Online (Sandbox Code Playgroud) 我正在寻找一种以Stream干净的方式优化处理的方法.
我有类似的东西:
try (Stream<Path> stream = Files.list(targetDir)) {
Map<String, List<Path>> targetDirFilteredAndMapped = stream.parallel()
.filter(path -> sd.containsKey(md5(path)))
.collect(Collectors.groupingBy(path -> md5(path)));
} catch (IOException ioe) { // manage exception }
Run Code Online (Sandbox Code Playgroud)
由于该md5功能非常昂贵,我想知道是否有办法每个文件只调用一次.
有什么建议?
我有一个字符串:
String ints = "1, 2, 3";
Run Code Online (Sandbox Code Playgroud)
我想将其转换为整数列表:
List<Integer> intList
Run Code Online (Sandbox Code Playgroud)
我可以通过这种方式将其转换为字符串列表:
List<String> list = Stream.of("1, 2, 3").collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
但不要列出整数.
有任何想法吗?
今天我试着重构这个代码,它从目录中的文件中读取id,
Set<Long> ids = new HashSet<>();
for (String fileName : fileSystem.list("my-directory")) {
InputStream stream = fileSystem.openInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
String line;
while ((line = br.readLine()) != null) {
ids.add(Long.valueOf(line.trim()));
}
br.close();
}
Run Code Online (Sandbox Code Playgroud)
使用流api
Set<Long> ids = fileSystem.list("my-directory").stream()
.map(fileName -> fileSystem::openInputStream)
.map(is -> new BufferedReader(new InputStreamReader(is)))
.flatMap(BufferedReader::lines)
.map(String::trim)
.map(Long::valueOf)
.collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)
然后我发现IO流不会被关闭,我没有看到一种简单的方法来关闭它们,因为它们是在管道内创建的.
有任何想法吗?
upd:示例中的FileSystem是HDFS,Files#lines不能使用类似的方法.
我正在尝试使用以下签名实现一个方法:
public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>>> iterator);
Run Code Online (Sandbox Code Playgroud)
方法的目标是将每个流类型展平为单个流并将输出包装成一对.我只有一个迭代器(不是Iterable),我不能改变方法签名,所以我必须在一次迭代中执行展平.
我目前最好的实施是
public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>> iterator) {
Stream<A> aStream = Stream.empty();
Stream<B> bStream = Stream.empty();
while(iterator.hasNext()) {
Pair<Stream<A>, Stream<B>> elm = iterator.next();
aStream = Stream.concat(aStream, elm.first);
bStream = Stream.concat(bStream, elm.second);
}
return Pair.of(aStream, bStream);
}
Run Code Online (Sandbox Code Playgroud)
虽然这在技术上是正确的,但我对此并不十分满意,原因有两个:
感觉Stream#flatMap应该适合这里(在使用Guava的Streams.stream(Iterator)将输入Iterator转换为Stream之后,但由于中间的Pair类型,它似乎不起作用.
另外一个要求是任何迭代器/流可能非常大(例如,输入可能包含从一对极大的流到一个项目流中的许多流的任何地方),因此理想情况下,解决方案不应包含收集结果. - 记忆收藏.
考虑以下WorkExperience课程:
public class WorkExperience {
private int year;
private List<Skills> skill;
public WorkExperience(int year, List<Skills> skill) {
this.year = year;
this.skill = skill;
}
//getter setter
}
public class Skills {
private String skills;
public Skills(String skills) {
this.skills = skills;
}
@Override
public String toString() {
return "Skills [skills=" + skills + "]";
}
}
Run Code Online (Sandbox Code Playgroud)
假设我希望按年份按照我的技能进行分组,这就是我们groupBy今年的表现:
public static void main(String[] args) {
List<Skills> skillSet1 = new ArrayList<>();
skillSet1.add(new Skills("Skill-1"));
skillSet1.add(new Skills("Skill-2"));
skillSet1.add(new Skills("Skill-3"));
List<Skills> skillSet2 …Run Code Online (Sandbox Code Playgroud) java ×10
java-8 ×10
java-stream ×10
collections ×1
collectors ×1
java-9 ×1
java-io ×1
regex ×1