小编Hol*_*ger的帖子

在Java Lambda中,为什么getClass()在捕获的变量上调用

如果你看一下字节码

Consumer<String> println = System.out::println;
Run Code Online (Sandbox Code Playgroud)

Java 8更新121生成的字节代码是

GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
DUP
INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
POP
INVOKEDYNAMIC accept(Ljava/io/PrintStream;)Ljava/util/function/Consumer; [
  // handle kind 0x6 : INVOKESTATIC
  java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
  // arguments:
  (Ljava/lang/Object;)V, 
  // handle kind 0x5 : INVOKEVIRTUAL
  java/io/PrintStream.println(Ljava/lang/String;)V, 
  (Ljava/lang/String;)V
]
ASTORE 1
Run Code Online (Sandbox Code Playgroud)

getClass()正在调用该方法System.out,结果被忽略.

这是间接空引用检查吗?

当然,如果你跑

PrintStream out = null;
Consumer<String> println = out::println;
Run Code Online (Sandbox Code Playgroud)

这会触发NullPointerException.

java lambda bytecode javac java-8

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

Java 8 - 在stream.map()中链接构造函数调用和setter

我上课了

class Foo{
    String name;
    // setter, getter
}
Run Code Online (Sandbox Code Playgroud)

它只有一个默认的构造函数.

然后,我试图Foo从一些字符串创建一个List :

Arrays.stream(fooString.split(","))
            .map(name -> {
                Foo x = new Foo();
                x.setName(name);
                return x;

            }).collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)

由于没有构造函数采用名称,我不能简单地使用方法引用.当然,我可以使用构造函数调用和setter将这三行提取到一个方法中,但有没有更好或简洁的方法呢?(不更改Foo,这是生成的文件)

java lambda java-8 java-stream

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

如果Map中的所有List值都为空/非空,则使用Streams返回Boolean

给定一个MapString到a 的映射List,有没有办法使用Java Streams返回一个布尔值,其中TRUE表示一个或多个列表有元素?如果地图中的所有列表都为空,则返回FALSE.

Map< String , List<String> > map = …
Run Code Online (Sandbox Code Playgroud)

可以使用Streams替换这个传统的代码吗?

// See if any diffs were found. Loop through the Map, look at each List of diffs to see if non-empty.
boolean anyElementsInAnyList = false;
for (List<String> list : map.values () ) {
    if (!list.isEmpty()) {
        anyElementsInAnyList = true;
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我们可以在第一次发现后突破检查.无需检查所有Map值(所有列表).如果为了效率,Stream可以执行相同的首次停止工作("短路"操作),那将是很好的.

java java-stream

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

如何创建通用分页拼接器?

我希望能够处理从必须在页面中访问的源读取的Java流.作为第一种方法,我实现了一个分页迭代器,它只是在当前页面用完项目时请求页面,然后用于StreamSupport.stream(iterator, false)获取迭代器上的流句柄.

当我发现我的页面获取非常昂贵时,我想通过并行流访问页面.在这一点上,我发现由于java直接从迭代器提供的spliterator实现,我的天真方法提供的并行性是不存在的.因为我实际上对我想要遍历的元素了解了很多(我知道在请求第一页后总结果数,并且源支持偏移和限制)我认为应该可以实现我自己的分裂器实现真正的并发(在页面元素和查询页面上完成的工作).

我已经能够很容易地实现"在元素上完成的工作"并发性,但在我最初的实现中,页面的查询只能由最顶层的分裂器完成,因此不会从分工中受益由fork-join实现提供.

如何编写实现这两个目标的分裂器?

作为参考,我将提供我到目前为止所做的事情(我知道它没有适当地划分查询).

   public final class PagingSourceSpliterator<T> implements Spliterator<T> {

    public static final long DEFAULT_PAGE_SIZE = 100;

    private Page<T> result;
    private Iterator<T> results;
    private boolean needsReset = false;
    private final PageProducer<T> generator;
    private long offset = 0L;
    private long limit = DEFAULT_PAGE_SIZE;


    public PagingSourceSpliterator(PageProducer<T> generator) {
        this.generator = generator;
    }

    public PagingSourceSpliterator(long pageSize, PageProducer<T> generator) {
        this.generator = generator;
        this.limit = pageSize;
    }


    @Override
    public boolean tryAdvance(Consumer<? super T> action) {

        if (hasAnotherElement()) {
            if …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream spliterator

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

Java 8流和地图值得吗?

感觉就像java 8流和映射函数那么冗长,它们并不是真正的改进.例如,我编写了一些使用集合生成另一个修改过的集合的代码:

private List<DartField> getDartFields(Class<?> model) {
    List<DartField> fields = new ArrayList<>();
    for (Field field : model.getDeclaredFields()) {
        if (!Modifier.isStatic(field.getModifiers())) {
            fields.add(DartField.getDartField(field));
        }
    }
    return fields;
}
Run Code Online (Sandbox Code Playgroud)

这似乎是java 8流及其功能的理想用例,所以我重写了它:

private List<DartField> getDartFields(Class<?> model) {
    return Arrays.asList(model.getDeclaredFields())
            .stream()
            .filter(field -> !Modifier.isStatic(field.getModifiers()))
            .map(field -> DartField.getDartField(field))
            .collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)

但我不确定我更喜欢那个.这是236个字符,而普通风格的java则是239个字符.它似乎没有或多或少可读.这是很好,你没有申报ArrayList,但需要打电话.collect(Collectors.toList())Arrays.asList(取决于数据类型)是没有任何好转.

使用.stream()这样的东西是否有一些实际的改进,我只是没有得到,或者这只是一个有趣的方式抛出任何同事不知道函数式编程的循环?

我想如果我动态地传递过滤器或映射lambdas它会很有用,但如果你不需要这样做......

java functional-programming java-8 java-stream

24
推荐指数
3
解决办法
5835
查看次数

将java.util.function.Function转换为Interface

在这个(简化的)示例中,我可以MyInterface通过使用方法引用来创建我的对象apply,但是直接转换不起作用.

@Test
public void testInterfaceCast(){
    Function<String, Integer> func = Integer::parseInt;

    MyInterface legal = func::apply; // works
    MyInterface illegal = func; // error
}

public interface MyInterface extends Function<String, Integer>{}
Run Code Online (Sandbox Code Playgroud)

第二个赋值给出了编译器错误:

incompatible types: Function<String,Integer> cannot be converted to MyInterface
Run Code Online (Sandbox Code Playgroud)

这个问题

我可以做一些泛型魔法,能够投射Function<T, R>到界面吗?

java java-8 method-reference

24
推荐指数
2
解决办法
2092
查看次数

私有接口方法的方法参考

请考虑以下代码:

public class A {
    public static void main(String[] args) {
        Runnable test1 = ((I)(new I() {}))::test;  // compiles OK
        Runnable test2 = ((new I() {}))::test;     // won't compile 
    }

    interface I {
        private void test() {}
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的不明白......我明白这种test()方法是私密的.但是,如果我们将匿名类强制转换为其接口,会发生什么变化((I)(new I() {}))?更确切地说,我希望看到一个允许该技巧的特定JLS点.

PS我已将其报告为编译器的错误(ID:9052217).在我看来,Runnable test2 = ((new I() {}))::test;在这种特殊情况下应该编译得很好.

PPS到目前为止,根据我的报告创建了一个错误:https://bugs.openjdk.java.net/browse/JDK-8194998.它可能会被关闭为"不会修复"或者什么.

java language-lawyer java-9

24
推荐指数
4
解决办法
1943
查看次数

Java 8流组合器从未调用过

我正在编写一个自定义java 8收集器,它应该计算具有getValue()方法的POJO的平均值.这是代码:

public static Collector<BoltAggregationData, BigDecimal[], BigDecimal> avgCollector = new Collector<BoltAggregationData, BigDecimal[], BigDecimal>() {

        @Override
        public Supplier<BigDecimal[]> supplier() {
            return () -> {
                BigDecimal[] start = new BigDecimal[2];
                start[0] = BigDecimal.ZERO;
                start[1] = BigDecimal.ZERO;
                return start;
            };
        }

        @Override
        public BiConsumer<BigDecimal[], BoltAggregationData> accumulator() {
            return (a,b) ->  {
                a[0] = a[0].add(b.getValue());
                a[1] = a[1].add(BigDecimal.ONE);
            };
        }

        @Override
        public BinaryOperator<BigDecimal[]> combiner() {
            return (a,b) -> {
                a[0] = a[0].add(b[0]);
                a[1] = a[1].add(b[1]);
                return a;
            };
        }

        @Override
        public Function<BigDecimal[], …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream collectors

23
推荐指数
2
解决办法
1125
查看次数

(编译器)否则if(true)vs else scenario

获取以下Java代码段:

....
    else if (true){ //hard-coded as true
     ///launch methodA
    }
    else {
     ///launch methodA (same code as in the ` else if ` statement)
    }
....
Run Code Online (Sandbox Code Playgroud)

我想知道的是编译器如何处理这个问题.编译器else if(true)完全删除语句以便不必执行检查是不合逻辑的,即使它被硬编码为真.特别是在Eclipse中,上面的代码是如何解释的?

或者在以下场景中如何:

....
    else if (true){ //hard-coded as true
     ///launch methodA
    }
    else {
     ///launch methodBB
    }
....
Run Code Online (Sandbox Code Playgroud)

在这种情况下编译器删除else语句不是合乎逻辑的吗?因为在运行时,else语句无法访问.

java compiler-construction if-statement language-lawyer

22
推荐指数
2
解决办法
2156
查看次数

Java 中的内存栅栏是做什么用的?

在试图了解SubmissionPublisherJava SE 10 中的源代码,OpenJDK | docs),在版本 9 中添加到 Java SE 的新类是如何实现的,我偶然发现了一些VarHandle我以前不知道的API 调用:

fullFenceacquireFencereleaseFenceloadLoadFencestoreStoreFence

在做了一些研究之后,特别是关于内存屏障/栅栏的概念(我以前听说过它们,是的;但从未使用过它们,因此对它们的语义非常不熟悉),我想我对它们的用途有了基本的了解. 尽管如此,由于我的问题可能源于误解,我想确保我首先做对了:

  1. 内存屏障是关于读写操作的重新排序约束。

  2. 内存屏障可以分为两大类:单向和双向内存屏障,这取决于它们是否对读取或写入或两者都设置了约束。

  3. C++ 支持多种内存屏障,但是,这些与VarHandle. 然而,一些在可用内存壁垒VarHandle提供排序的影响兼容其相应的C ++内存屏障。

    • #fullFence 兼容 atomic_thread_fence(memory_order_seq_cst)
    • #acquireFence 兼容 atomic_thread_fence(memory_order_acquire)
    • #releaseFence 兼容 atomic_thread_fence(memory_order_release)
    • #loadLoadFence并且#storeStoreFence没有兼容的 C++ 计数器部分

兼容这个词在这里似乎非常重要,因为在细节方面语义明显不同。例如,所有 C++ 屏障都是双向的,而 Java 的屏障不是(必然)。

  1. 大多数内存屏障也具有同步效应。那些特别依赖于其他线程中使用的屏障类型和先前执行的屏障指令。由于屏障指令的全部含义是特定于硬件的,因此我将坚持使用更高级别的 (C++) 屏障。例如,在 C++ 中,在释放屏障指令之前所做的更改对于执行获取屏障指令的线程是可见的。

我的假设正确吗?如果是这样,我产生的问题是:

  1. 可用的内存屏障是否VarHandle会导致任何类型的内存同步? …

java concurrency memory-model java-memory-model memory-barriers

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