如果你看一下字节码
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.
我上课了
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
,这是生成的文件)
给定一个Map
String到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流.作为第一种方法,我实现了一个分页迭代器,它只是在当前页面用完项目时请求页面,然后用于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 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它会很有用,但如果你不需要这样做......
例
在这个(简化的)示例中,我可以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>
到界面吗?
请考虑以下代码:
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 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代码段:
....
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
语句无法访问.
在试图了解SubmissionPublisher
(Java SE 10 中的源代码,OpenJDK | docs),在版本 9 中添加到 Java SE 的新类是如何实现的,我偶然发现了一些VarHandle
我以前不知道的API 调用:
fullFence
,acquireFence
,releaseFence
,loadLoadFence
和storeStoreFence
。
在做了一些研究之后,特别是关于内存屏障/栅栏的概念(我以前听说过它们,是的;但从未使用过它们,因此对它们的语义非常不熟悉),我想我对它们的用途有了基本的了解. 尽管如此,由于我的问题可能源于误解,我想确保我首先做对了:
内存屏障是关于读写操作的重新排序约束。
内存屏障可以分为两大类:单向和双向内存屏障,这取决于它们是否对读取或写入或两者都设置了约束。
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 的屏障不是(必然)。
我的假设正确吗?如果是这样,我产生的问题是:
可用的内存屏障是否VarHandle
会导致任何类型的内存同步? …
java concurrency memory-model java-memory-model memory-barriers
java ×10
java-8 ×6
java-stream ×5
lambda ×2
bytecode ×1
collectors ×1
concurrency ×1
if-statement ×1
java-9 ×1
javac ×1
memory-model ×1
spliterator ×1