我刚刚开始使用Java 8 lambdas,我正在尝试实现一些我在函数式语言中习惯的东西。
例如,大多数函数式语言都有某种find函数,它对序列或列表进行操作,返回谓词为真的第一个元素。我认为在Java 8中实现这一目标的唯一方法是:
lst.stream()
.filter(x -> x > 5)
.findFirst()
然而,这似乎对我来说效率很低,因为过滤器会扫描整个列表,至少在我的理解(这可能是错误的)。有没有更好的办法?
我刚刚开始使用Java 8 lambdas,我正在尝试实现一些我在函数式语言中习惯的东西。
例如,大多数函数式语言都有某种find函数,它对序列或列表进行操作,返回谓词为真的第一个元素。我认为在Java 8中实现这一目标的唯一方法是:
lst.stream()
.filter(x -> x > 5)
.findFirst()
然而,这似乎对我来说效率很低,因为过滤器会扫描整个列表,至少在我的理解(这可能是错误的)。有没有更好的办法?
对于一个挑战,一位代码高尔夫球手编写了以下代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
int size = 3;
String[] array = new String[size];
Arrays.fill(array, "");
for (int i = 0; i <= 100;) {
array[i++ % size] += i + " ";
}
for (String element: array) {
System.out.println(element);
}
}
}
当在Java 8中运行这段代码时,我们得到以下结果:
1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 61 64 67 70 73 76 79 82 85 88 91 94 97 100
2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 62 65 68 71 74 77 80 83 86 89 92 95 98 101
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99
当在Java 10中运行这段代码时,我们得到以下结果:
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 102
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
在Java 10中,这种编号完全不存在。这里发生了什么?这是Java 10中的bug吗?
评论跟进:
The issue appears when compiled with Java 9 or later (we found it in Java 10). Compiling this code on Java 8, then running in Java 9 or any later version, including Java 11 early access, gives the expected result. This kind of code is non-standard, but is valid according to the spec. It was found by Kevin Cruijssen in a discussion in a golfing challenge, hence the weird use case encountered. Didier L simplified the issue with this much smaller and more understandable code: class Main { public static void main(String[] args) { String[] array = { "" }; array[test()] += "a"; } static int test() { System.out.println("evaluated"); return 0; } } Result when compiled in Java 8: evaluated Result when compiled in Java 9 and 10: evaluated evaluated The issue seems to be limited to the string concatenation and assignment operator (+=) with an expression with side effect(s) as the left operand, like in array[test()]+="a", array[ix++]+="a", test()[index]+="a", or test().field+="a". To enable string concatenation, at least one of the sides must have type String. Trying to reproduce this on other types or constructs failed.
如果我有一个List<List<Object>>,我如何使用Java8的特性将其转换为包含相同迭代顺序的所有对象的List<Object>?
在Java 8中,Stream.map()和Stream.flatMap()方法之间有什么区别?
使用IntelliJ IDE不能编译任何项目。设置截图如下:
使用JDK:
项目SDK及语言级别:
语言水平:
有人有什么想法吗?
将Java 8流转换为数组的最简单/最短的方法是什么?
我想使用Java 8的流和lambdas将对象列表转换为Map。
这是我在Java 7及以下版本中编写它的方式。
private Map<String, Choice> nameMap(List<Choice> choices) {
final Map<String, Choice> hashMap = new HashMap<>();
for (final Choice choice : choices) {
hashMap.put(choice.getName(), choice);
}
return hashMap;
}
我可以很容易地完成这一点使用Java 8和番石榴,但我想知道如何做到这一点没有番石榴。
番石榴:
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, new Function<Choice, String>() {
@Override
public String apply(final Choice input) {
return input.getName();
}
});
}
番石榴和Java 8 lambdas。
private Map<String, Choice> nameMap(List<Choice> choices) {
return Maps.uniqueIndex(choices, Choice::getName);
}
我在研究Java 8源代码时,发现这部分代码非常令人惊讶:
// Defined in IntPipeline.java
@Override
public final OptionalInt reduce(IntBinaryOperator op) {
return evaluate(ReduceOps.makeInt(op));
}
@Override
public final OptionalInt max() {
return reduce(Math::max); // This is the gotcha line
}
// Defined in Math.java
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
max是一个方法指针吗?一个正常的静态方法如何转换为IntBinaryOperator?
编者注:这个问题是在2014年提出的,答案可能已经过时了。
我想用最新的JavaFX编程,它需要Java 8。我使用的是IntelliJ 13 CE和Mac OS X 9 Mavericks。我运行了Oracle的Java 8安装程序,文件看起来像是在
/Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk
但以前的版本是
/System/Library/Java/JavaFrameworks/jdk1.6....
不知道为什么最新的安装程序把这个放在/Library而不是/System/Library(也不知道有什么区别)。但是/usr/libexec/java_home找不到1.8,所以我找到的所有关于如何设置当前java版本的帖子都不起作用。我已经尝试添加了一个符号链接,使它看起来像1.8在/System/Library中…路径,但没有用。/usr/libexec/java_home -V仍然只列出旧的Java 1.6。
讽刺的是,在“系统首选项”下的“Java”控制面板只显示Java 1.8!
为什么Oracle的安装程序不把它放在它真正应该去的地方?我该如何解决这个问题呢?