标签: java-stream

什么是使Java8流生成格式化字符串的高效方法

上下文:给定一个目录,我想在列表中列出其名称中包含模式的所有文件,按lastModified时间戳排序,并将此列表格式化为Json字符串,我将获取每个文件的名称和时间戳:

[{"name": "somefile.txt", "timestamp": 123456},
{"name": "otherfile.txt", "timestamp": 456789}]
Run Code Online (Sandbox Code Playgroud)

我有以下代码:

private StringBuilder jsonFileTimestamp(File file) {
    return new StringBuilder("{\"name\":\"")
            .append(file.getName())
            .append("\", \"timestamp\":")
            .append(file.lastModified())
            .append("}");
}

public String getJsonString(String path, String pattern, int skip, int limit) throws IOException {

    return Files.list(Paths.get(path))
            .map(Path::toFile)
            .filter(file -> {
                return file.getName().contains(pattern);
            })
            .sorted((f1, f2) -> {
                return Long.compare(f2.lastModified(), f1.lastModified());
            })
            .skip(skip)
            .limit(limit)
            .map(f -> jsonFileTimestamp(f))
            .collect(Collectors.joining(",", "[", "]"));
}
Run Code Online (Sandbox Code Playgroud)

这很好用.我只关心StringBuilder实例化(或字符串连接)的性能.只要文件数量很少就可以了(这是我的情况,所以我很好),但我很好奇:你会建议什么作为优化?我觉得我应该使用reduce正确的累加器和组合器,但我不能让我的大脑围绕它.

谢谢.


UPDATE

我终于进行了以下"优化":

private StringBuilder jsonFileTimestampRefactored(StringBuilder res, File file) {
    return res.append(res.length() …
Run Code Online (Sandbox Code Playgroud)

java optimization string-formatting java-8 java-stream

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

我和for stream有不同的结果,为什么?

我有Flyweight模式,我尝试将循环转换为流,但结果是不同的:

public Line getLine(Color color) {
    for(Line line: pool) {
        if(line.getColor().equals(color)) {
            return line;
        } 
    }        
    return createLine(color);
}

factory.getLine(Color.RED);
factory.getLine(Color.RED);
System.out.println(getPool().size()); // print 1
Run Code Online (Sandbox Code Playgroud)

重构代码:

public Line getLine(Color color) {
    return pool.stream()
               .filter(l -> l.getColor().equals(color))                   
               .findFirst()                   
               .orElse(createLine(color));
}

factory.getLine(Color.RED);
factory.getLine(Color.RED);
System.out.println(getPool().size()); // print 2
Run Code Online (Sandbox Code Playgroud)

流有什么问题?

java for-loop java-8 java-stream

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

在任何其他中间方法之前,如何在打开Java 8流时运行单个函数?

老实说,除了相邻的代码行之外,我还不确定这是否可行.但是,我想我会和社区核实一下.

Java 8允许通过Stream API管理其集合.我们以前需要外部迭代的地方,现在我们可以简单地使用:

<Collection>.stream().forEach([expression]);
Run Code Online (Sandbox Code Playgroud)

当我尝试快速格式化大型集合时,这很好,比如,将它输出到BufferedOutputStream或其他目标.我需要做的是在我旁边写一些关于我正在写的内容的信息.到目前为止,我能想到的最好的是:

labelData();
firstNames.stream().sequential().forEach(sz -> reportData(sz));
Run Code Online (Sandbox Code Playgroud)

然而,如果我可以这样的话,那将是非常好的:

firstNames.stream().sequential().
    .onOpen(labelData())
    .forEach(sz->reportData(sz));
Run Code Online (Sandbox Code Playgroud)

我知道可以使用BaseStream.onClose(Runnable closeHandler)设置一个on-close方法.这种方法是否存在开放?

谢谢你的时间.

java handler java-8 java-stream

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

java 8 stream groupBy和创建新对象

假设我有两个类C1和C2,其中C2由C1的构造函数使用:

public class C1
{
    public C1( C2 o2 ){ ... }

    public String getProperty()
    {
        String result;
        ...
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有了一个C2对象列表(列表列表),我想使用从流C2对象创建的C1的getProperty()上的条件来流式传输和过滤。

有没有办法用流来做到这一点?

List<C2> list = ...
List<C2> result = list.stream().filter( XXXX )
Run Code Online (Sandbox Code Playgroud)

我猜我应该有XXXX,它使用流中的C2对象创建一个C1对象并比较其getProperty()(例如,“ value” .equals(o2.getProperty()))

这有可能吗?

java lambda java-8 java-stream

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

使用lambdas和流从字节数组中获取十六进制字符串的有效方法

这是如何从字节数组创建IntStream的后续问题?

我创建了一个方法将给定的字节数组转换为连接的十六进制字符

static String bytesToHex(final byte[] bytes) {

    return IntStream.rang(0, bytes.length * 2)
        .map(i -> (bytes[i / 2] >> ((i & 0x01) == 0 ? 4 : 0)) & 0x0F)
        .mapToObj(Integer::toHexString)
        .collect(joining());
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,不使用任何第三方库,上面的代码是否足够有效?我做错了什么或不必要的吗?

lambda hex java-8 java-stream

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

使用Java 8合并流

在阅读了关于流的内容后,我现在尝试使用它们,并且已经通过简单的示例出现了第一个问题.我想实现一个非常简单的加密算法,它使用替换.有一些文本需要加密:

static List<Integer> text = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
Run Code Online (Sandbox Code Playgroud)

有一些密码:

private List<Integer> password = Arrays.asList(1, 5, 7, 3);
Run Code Online (Sandbox Code Playgroud)

现在的想法是将密码值添加到文本值.结果应该是

1 + 1,2 + 5,3 + 7,4 + 3,5 + 1,6 + 5 ......

所以我必须从密码创建一个流,它从到达上面列表末尾的开头开始.这部分我已经设法做到了.

现在我不得不将2个流合并为1个流.任何想法,如何实现?

lambda java-8 java-stream

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

Java8:减少像sql group by这样的元素列表

在stream().filter().map()列表上有一个类似的数据结构,List<List<Object>>如下所示:

[["1","a",20],
 ["1","b",10],
 ["2","a",10],
 ["2","b",30]]
Run Code Online (Sandbox Code Playgroud)

我想要的是按内部列表的第一个元素的值进行分组,保留中间元素,最后将每个"组"的最后元素相加.

[["1", 30],
 ["2", 40]]
Run Code Online (Sandbox Code Playgroud)

对不起,如果这对你们中的一些人来说很明显,但我还没有找到如何实现这一目标的任何例子.我假设它可以通过Stream.reduce(U身份,BiFunction累加器,BinaryOperator组合器)来完成,但到目前为止我还没有成功.如果有人可以为此提供一些示例代码,我相信它也会受到许多其他人的赞赏.

reduce functional-programming java-8 java-stream

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

用于输入数据的Java 8 Stream实用程序

想象一下,通过回调或InputStream您需要不断转换为Java 8的某种传入数据Stream.我们不知道传入的数据流何时停止,但我们知道它可以停止.

到目前为止,我已经看到了解决这个问题的两种方法,我对如何实现这一目标的最佳实践感兴趣.主要是因为我必须是某人以前面对的事情.必须有比下面的想法更简单的方法.

1)最简单的方法是将源视为a Supplier并仅用于Stream.generate提供数据:

Stream.generate(() -> blockCallToGetData());
Run Code Online (Sandbox Code Playgroud)

然而,这具有缺点,即流永远不会结束.因此,只要输入源停止发送,流就会一直调用该方法.除非我们自然地抛出一个Runtime异常,但这可能会变得很难看.

2)第二个想法是使用a Iterator(转换为a Spliterator)next方法阻塞,直到我们找到下一个元素.作为一个粗略的例子:

class BlockingIterator implements Iterator<Data> {

  @Override void boolean hasNext() {
    return true;
  }

  @Override Data next() {
    return blockCallToGetData();
  }

}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是,我可以通过返回停止流false的hasNext方法.但是,在我们不控制传入数据速度的情况下(例如在回调中),我们需要为迭代器保留一个就绪元素的缓冲区.在有人调用next迭代器之前,这个缓冲区可能会变得无限大.

所以,我的问题是; 将阻塞输入提供给流的最佳做法是什么?

java parsing java-8 java-stream

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

并行流上的skip()是否存在一个好的用例?


2015年9月编辑


当我最初问这个问题,2015年2月,在报道的行为所链接的问题是反直觉的,但那种规范允许(尽管在文档一些小的矛盾).

然而,Tagir Valeev在2015年6月问了一个新问题,我认为他清楚地证明了这个问题中报告的行为实际上是一个错误.Brain Goetz回答了他的问题,并承认,当一个终端操作触发时,不会阻止on 的特性的反向传播是一个错误,这个终端操作不会被迫尊重元素的遭遇顺序(例如) .此外,在他自己的回答的评论中,他分享了JDK的错误跟踪系统中发布的问题的链接.UNORDEREDStreamskip()forEach()

该问题的状态现已解决,其修复版本为9,这意味着该修复程序将在JDK9中可用.但是,它也被反向移植到JDK8 update 60,build 22.

所以从JDK8u60-b22开始,这个问题再也没有意义了,因为现在skip()表现得像直觉一样,甚至在并行流上也是如此.


我原来的问题是......


最近我和一些同事讨论了这件事.我说skip()在并行流上使用它是没用的,因为它似乎没有一个很好的用例.他们告诉我有关性能提升,FJ池处理,jvm可用的核心数量等等,但他们无法给我任何实际的使用示例.

skip()并行流是否存在良好的用例?

在这里看到这个问题.请阅读问题和答案以及评论,因为那里有很多好的论据.

theory parallel-processing java-8 java-stream

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

有没有办法找到匹配谓词的第一个元素?

使用Java 8+,您可以轻松找到与a匹配的集合的所有元素Predicate.

someCollection.stream().filter(somePredicate)
Run Code Online (Sandbox Code Playgroud)

然后你可以找到第一个元素:

someCollection.stream().filter(somePredicate).findFirst()
Run Code Online (Sandbox Code Playgroud)

但问题是,它会Predicate针对所有元素运行.有没有一种干净的方法只能运行Predicate反对元素,直到找到第一个匹配,然后返回它,就像它一样anyMatch(但返回一个boolean告知是否找到一个)?

java performance filtering predicate java-stream

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