标签: java-stream

收集HashSet/Java 8/Regex Pattern/Stream API

最近我更改了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编写此代码?

java regex collections java-8 java-stream

14
推荐指数
3
解决办法
6202
查看次数

如何计算流过滤器上的匹配?

如何计算流过滤器的匹配?我正在尝试将以下代码重构为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多次重复使用.如何使用流实现相同的功能?

java java-8 java-stream

14
推荐指数
1
解决办法
3万
查看次数

连接并行流

假设我有两个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)

java parallel-processing java-8 java-stream

14
推荐指数
1
解决办法
1000
查看次数

如何将Java流转换为滑动窗口?

将流转换为滑动窗口的推荐方法是什么?

例如,在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 java-8 java-stream

14
推荐指数
4
解决办法
7406
查看次数

Java 8修改流元素

我想用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)

java java-8 java-stream

14
推荐指数
3
解决办法
4万
查看次数

Java 8 Stream通过相同的昂贵方法调用进行过滤和分组

我正在寻找一种以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功能非常昂贵,我想知道是否有办法每个文件只调用一次.

有什么建议?

java java-8 java-stream

14
推荐指数
3
解决办法
1569
查看次数

Java 8将int的int转换为List <Integer>

我有一个字符串:

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)

但不要列出整数.

有任何想法吗?

java java-8 java-stream collectors

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

在Stream API中使用AutoClosable接口

今天我试着重构这个代码,它从目录中的文件中读取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不能使用类似的方法.

java java-io java-8 java-stream autocloseable

14
推荐指数
1
解决办法
852
查看次数

Java flatmap Iterator <Pair <Stream <A>,Stream <B >>>对<Stream <A>,Stream <B >>

我正在尝试使用以下签名实现一个方法:

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)

虽然这在技术上是正确的,但我对此并不十分满意,原因有两个:

  1. Stream.concat警告不要这样做,因为它可能导致StackOverflowError.
  2. 在风格上,我宁愿它是纯粹的功能,如果可能的话,而不是必须遍历迭代器并重新分配流.

感觉Stream#flatMap应该适合这里(在使用Guava的Streams.stream(Iterator)将输入Iterator转换为Stream之后,但由于中间的Pair类型,它似乎不起作用.

另外一个要求是任何迭代器/流可能非常大(例如,输入可能包含从一对极大的流到一个项目流中的许多流的任何地方),因此理想情况下,解决方案不应包含收集结果. - 记忆收藏.

java java-8 java-stream

14
推荐指数
2
解决办法
1211
查看次数

将列表流转换为单个Container

考虑以下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 java-8 java-stream java-9

14
推荐指数
2
解决办法
429
查看次数