我们知道Java 8引入了一个新的Stream API, java.util.stream.Collector是定义如何聚合/收集数据stream的接口。 但是,收集器接口是这样devise的: public interface Collector<T, A, R> { Supplier<A> supplier(); BiConsumer<A, T> accumulator(); BinaryOperator<A> combiner(); Function<A, R> finisher(); } 为什么它不是像下面这样devise的? public interface Collector<T, A, R> { A supply(); void accumulate(A accumulator, T value); A combine(A left, A right); R finish(A accumulator); } 后者更容易实现。 devise它作为前者的考虑是什么?
采取以下行示例代码: Set<String> someSet = someColletion.stream().map(p -> p.toString()).collect(Collectors.toSet()); 我想要一个HashSet 。 把一个debugging器的代码,我确实得到一个HashSet 。 我看了一下java.util.stream.Collectors.toSet()来观察下面的代码: public static <T> Collector<T, ?, Set<T>> toSet() { return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add, (left, right) -> { left.addAll(right); return left; }, CH_UNORDERED_ID); } 合约保证一个Set ,实现决定一个HashSet ; 看起来合理。 但是,我的实现需要由HashSet保证的恒定时间查找,而不仅仅是任何旧的Set 。 如果toSet()的实现决定使用FooSet ,这完全在它的权限之内,那么我的实现就会受到影响。 这个问题的最佳实践解决scheme是什么?
为什么这会抛出一个java.lang.NullPointerException ? List<String> strings = new ArrayList<>(); strings.add(null); strings.add("test"); String firstString = strings.stream() .findFirst() // Exception thrown here .orElse("StringWhenListIsEmpty"); //.orElse(null); // Changing the `orElse()` to avoid ambiguity strings的第一项是null ,这是一个完全可以接受的值。 此外, findFirst()返回一个Optional ,这对于findFirst()能够处理null来说更为findFirst() 。 编辑:更新orElse()更不明确。
有时我想在一个stream上执行一组操作,然后用其他操作以两种不同的方式处理结果stream。 我能做到这一点,而不必指定两次通用的初始操作? 例如,我希望有一个如下所示的dup()方法: Stream [] desired_streams = IntStream.range(1, 100).filter(n -> n % 2 == 0).dup(); Stream stream14 = desired_streams[0].filter(n -> n % 7 == 0); // multiples of 14 Stream stream10 = desired_streams[1].filter(n -> n % 5 == 0); // multiples of 10
我有映射Map<Type, Long> countByType ,我想有一个列表已按sorting(最小到最大)的键相应的值。 我的尝试是: countByType.entrySet().stream().sorted().collect(Collectors.toList()); 然而,这只是给了我一个条目列表,我怎样才能得到一个types的列表,而不会失去顺序?
我刚刚阅读了关于分支预测的内容 ,想试试Java 8 Streams如何工作。 然而Streams的performance总是比传统的循环更糟糕。 int totalSize = 32768; int filterValue = 1280; int[] array = new int[totalSize]; Random rnd = new Random(0); int loopCount = 10000; for (int i = 0; i < totalSize; i++) { // array[i] = rnd.nextInt() % 2560; // Unsorted Data array[i] = i; // Sorted Data } long start […]
这个问题不是关于HashMap不是线程安全的,而是关于它在HotSpot和JDK代码上的特定失败模式的众所周知和logging的事实。 我很惊讶这个代码在NPE中失败了: public static void main(String[] args) { Map<Integer, Integer> m = new HashMap<>(0, 0.75f); IntStream.range(0, 5).parallel().peek(i -> m.put(i, i)).map(m::get).count(); } 关于NPE来自哪里,没有什么神秘之处:在.map(m::get)步骤中,尝试解开null 。 5次运行中约有4次失败。 在我的机器上, Runtime#availableProcessors()报告8,所以推测5的长度范围被分成5个子任务,每个只有一个成员。 我也假设我的代码在解释模式下运行。 它可能会调用JIT编译的HashMap或Stream方法,但顶层被解释,因此排除了HashMap状态被加载到线程局部内存(寄存器/堆栈)的任何变化,从而推迟了由另一个线程观察更新。 如果五个put操作中的某些操作在同一时间不在同一个内核上执行,我不希望它破坏HashMap的内部结构。 考虑到工作量不大,个人任务的时间安排必须非常精确。 是否真的是准确的时间( commonPool的线程必须被commonPool ),还是有其他的途径导致Oracle / OpenJDK HotSpot失败? 我目前的版本是 java version "1.8.0_72" Java(TM) SE Runtime Environment (build 1.8.0_72-b15) Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode) […]
我正在使用Java 8stream来迭代列表与子列表。 外部列表大小在100到1000之间变化(不同的testing运行),内部列表大小总是5。 有2个基准运行,performance出意想不到的性能偏差。 package benchmark; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole; import java.io.IOException; import java.util.concurrent.ThreadLocalRandom; import java.util.*; import java.util.function.*; import java.util.stream.*; @Threads(32) @Warmup(iterations = 25) @Measurement(iterations = 5) @State(Scope.Benchmark) @Fork(1) @BenchmarkMode(Mode.Throughput) public class StreamBenchmark { @Param({"700", "600", "500", "400", "300", "200", "100"}) int outerListSizeParam; final static int INNER_LIST_SIZE = 5; List<List<Integer>> list; Random rand() { return […]
我正在玩Java 8的stream,不能理解我得到的性能结果。 我有2核心CPU(英特尔i73520M),Windows 8的64位和64位Java 8更新5.我正在做简单的地图串stream/并行串stream,发现并行版本有点慢。 当我运行这个代码: String[] array = new String[1000000]; Arrays.fill(array, "AbabagalamagA"); Stream<String> stream = Arrays.stream(array); long time1 = System.nanoTime(); List<String> list = stream.map((x) -> x.toLowerCase()).collect(Collectors.toList()); long time2 = System.nanoTime(); System.out.println((time2 – time1) / 1000000f); …我得到了600左右的结果。这个版本,使用并行stream: String[] array = new String[1000000]; Arrays.fill(array, "AbabagalamagA"); Stream<String> stream = Arrays.stream(array).parallel(); long time1 = System.nanoTime(); List<String> list = […]
我想在下面的“Collectors.toMap()”调用中为“keyMapper”函数参数提供一个更简洁的expression式: List<Person> roster = …; Map<String, Person> map = roster .stream() .collect( Collectors.toMap( new Function<Person, String>() { public String apply(Person p) { return p.getLast(); } }, Function.<Person>identity())); 看来我应该能够使用lambdaexpression式来embedded它,但我不能拿出一个编译。 (我对lambda非常陌生,所以这并不令人意外。) 谢谢。 – >更新: 正如接受的答案中指出的那样 Person::getLast 是我一直在寻找的,而且是我曾经尝试过的。 然而,Eclipse 4.3的夜晚版本是个问题 – 它标记为错误的。 从命令行编译(我应该在发布之前完成),它工作。 那么,现在是时候用eclipse.org提交一个bug了。 谢谢。