[英]How can I make JUnit 4.8 run code after a failed test, but before any @After methods?
[英]How can I run a single function on the opening of a Java 8 stream, before any other intermediate methods?
老实说,我什至不确定在相邻代码行之外这是否可行。 但是,我认为我会向社区询问。
Java 8允许通过Stream API管理其Collection。 在以前需要外部迭代的地方,现在我们可以简单地使用:
<Collection>.stream().forEach([expression]);
当我尝试快速格式化大型集合并将其输出到BufferedOutputStream或其他某个目标时,这非常好。 我需要做的是在我旁边写一些信息。 到目前为止,我能想到的最好的方法是:
labelData();
firstNames.stream().sequential().forEach(sz -> reportData(sz));
而如果我可以这样做,那将是非常不错的事情:
firstNames.stream().sequential().
.onOpen(labelData())
.forEach(sz->reportData(sz));
我知道可以使用BaseStream.onClose(Runnable closeHandler)设置打开-关闭方法。 是否存在这种开放方法?
谢谢你的时间。
这个怎么样:
labelData();
firstNames.forEach(this::reportData);
有时,简单的答案会更好。
这就是map()的作用。
firstNames.map(e -> addLabel(e)).forEach(this::reportData);
map()是一个中间操作,它在处理每个元素时对其进行转换。
例如,代码:
Stream.of("One","Two", "Three", "Four");
.map(e -> "Number " + e)
.forEach(System.out::println);
将输出:
Number One
Number Two
Number Three
Number Four
如果您真的只想在流之前写一些东西,那就这样做。 无论如何,在流中调用它的效率要低得多。 如果只需要在流包含元素的情况下将其写出,则可以执行以下操作:
package stream;
public class OneTimePrinter {
private boolean shouldPrint = true;
public void print(Object o){
if (shouldPrint){
System.out.println(o);
shouldPrint = false;
}
}
}
然后在peek()操作中使用该OneTimePrinter类:
OneTimePrinter printer1 = new OneTimePrinter();
Stream.of("Five","Six", "Seven", "Eight")
.peek((e) -> printer1.print("TEST OUTPUT:\n------------"))
.map(e -> "Number " + e)
.forEach(System.out::println);
OneTimePrinter printer2 = new OneTimePrinter();
Stream.of()
.peek((e) -> printer2.print("TEST OUTPUT:\n------------"))
.map(e -> "Number " + e)
.forEach(System.out::println);
将输出:
TEST OUTPUT:
------------
Number Five
Number Six
Number Seven
Number Eight
在执行forEach()之前只调用labelData()函数仍然更容易,更高效。 出于好奇,我想出了三种不同的方法来执行此操作,并使用以下代码对一百万个元素流进行了测试:
首先,一种新型的收集器将执行操作并返回原始流:
public interface StreamOpenCollector<T> extends Collector<T, Object, Stream<T>> {
static <T> Collector<T, Object, Stream<T>> onOpen(Object arg, Consumer<Object> consumer){
return Collectors.collectingAndThen(Collectors.toList(), (list) -> {
consumer.accept(arg);
return list.stream();
});
}
}
然后是前面提到的OneTimePrinter,然后是测试类:
public class StreamOnOpenTest {
LinkedHashMap<String, Long> times = new LinkedHashMap<String, Long>();
public static void main(String[] args) {
StreamOnOpenTest test = new StreamOnOpenTest();
test.addTime("SkipMethod", test.time(IntStream.range(0, 1000000).mapToObj(e -> "" + e), (stream) -> {
stream
.skip(StreamOnOpenTest.labelData())
.map(e -> "Number " + e)
.forEach(System.out::println);
}));
test.addTime("PeekMethod", test.time(IntStream.range(0, 1000000).mapToObj(e -> "" + e), (stream) -> {
OneTimePrinter printer = new OneTimePrinter();
stream
.peek((e) -> printer.print("TEST OUTPUT:\n------------"))
.map(e -> "Number " + e)
.forEach(System.out::println);
}));
test.addTime("CollectMethod", test.time(IntStream.range(0, 1000000).mapToObj(e -> "" + e), (stream) -> {
stream
.collect(StreamOpenCollector.onOpen("TEST OUTPUT:\n------------", System.out::println))
.map(e -> "Number " + e)
.forEach(System.out::println);
}));
test.printTimes();
}
private void addTime(String key, long value){
times.put(key, value);
}
private void printTimes() {
System.out.println("------------\n------------\n");
times.forEach((key, value) -> System.out.println("For " + key + ", time was " + value + " milliseconds"));
}
private long time(Stream<String> stream, Consumer<Stream<String>> consumer){
long startTime = System.currentTimeMillis();
consumer.accept(stream);
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
private static int labelData(){
System.out.println("TEST OUTPUT:");
System.out.println("------------");
return 0;
}
}
经过三个运行的最终结果是:
--RUN 1--
For SkipMethod, time was 3479 milliseconds
For PeekMethod, time was 3574 milliseconds
For CollectMethod, time was 3593 milliseconds
--RUN 2--
For SkipMethod, time was 3603 milliseconds
For PeekMethod, time was 3684 milliseconds
For CollectMethod, time was 3718 milliseconds
--RUN 3--
For SkipMethod, time was 3534 milliseconds
For PeekMethod, time was 3540 milliseconds
For CollectMethod, time was 3606 milliseconds
如您所见,skip方法始终更快,但不必担心,除非您正在处理流中的数十亿个项目。
正如已经回答的, .map()是您要寻找的。
但我想指出一些我认为需要做的事情: labelData()对firstNames产生了副作用(它看起来像是字段/全局变量)。
对我来说,副作用在函数式编程中并不好,因为它们会引入状态。 这就是流避免出现状态的原因之一。
同样听起来很奇怪,您没有在最后收集流,而是在报告每个元素。 但这可能是由于您的示例简化了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.