我正在使用EclipseLink(2.5.1,也尝试过2.5.2-M1)构建一个java SE 8(oracle 1.8.0-b129)应用程序,并且有一个实体类,即使被正确注释,也只是被EclipeLink忽略了.在persistence.xml文件中引用.日志显示没有提及类,没有为它生成模式,等等.使用实体给出'抽象模式类型未知'错误.
我想我终于找到了原因,并认为我会分享.显然,EclipseLink不喜欢带有lambda表达式的类.这是一个简单的类来重现问题:
@Entity
public class LambdaEntity {
@Id
private Integer id;
public void theLambda() {
Arrays.asList(1, 2, 3).stream().filter(m -> m == 2);
}
}
Run Code Online (Sandbox Code Playgroud)
lambda表达式甚至不必使用持久属性,它在类中的简单存在就足够了.有谁知道是什么原因引起的?我猜测EclipeLink会对生成的字节码产生阻塞,但我发现很奇怪它会默默地忽略该类.
如果您尝试在与其他实体的关联中使用此实体,EclipseLink将提供错误,指出该实体未在该persistence.xml文件中定义.stacktrace的一部分:
Local Exception Stack:
Exception [EclipseLink-30005] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.PersistenceUnitLoadingException
Exception Description: An exception was thrown while searching for persistence archives with ClassLoader: sun.misc.Launcher$AppClassLoader@3b9a45b3
Internal Exception: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [hcm-test] failed.
Internal Exception: Exception [EclipseLink-7250] (Eclipse Persistence …Run Code Online (Sandbox Code Playgroud) 正如您所知,您可以在Java 8中使用lambdas,例如替换匿名方法.
这里可以看到Java 7与Java 8的一个例子:
Runnable runnable = new Runnable() {
@Override
public void run() {
checkDirectory();
}
};
Run Code Online (Sandbox Code Playgroud)
在Java 8中可以表示为以下两种方式:
Runnable runnable = () -> checkDirectory();
Run Code Online (Sandbox Code Playgroud)
要么
Runnable runnable = this::checkDirectory;
Run Code Online (Sandbox Code Playgroud)
这是因为它Runnable是一个功能接口,只有一个(抽象)公共非默认方法.
但是......因为TimerTask我们有以下内容:
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
checkDirectory();
}
};
Run Code Online (Sandbox Code Playgroud)
看起来很熟悉吧?
使用lambda表达式不起作用,因为它TimerTask是一个抽象类,即使它只有一个抽象的公共非默认方法,它也不是一个接口,因此也没有功能接口.
它也没有重构为具有默认实现的接口,因为它带有状态,因此无法完成.
所以我的问题:构建时有没有办法使用lambdas TimerTask?
我想要的是以下内容:
Timer timer = new Timer();
timer.schedule(this::checkDirectory, 0, 1 * 1000);
Run Code Online (Sandbox Code Playgroud)
而不是一些丑陋的匿名内部类,有没有办法让它更好?
我试图在java中使用lambda表达式创建一个示例,我正在使用官方JDK8.我的例子运行成功.但是当我试图检查编译器如何将lambda表达式转换为字节代码时,这让我有些困惑.以下是我的例子的代码: -
public class LambdaTest {
public Integer lambdaBinaryOpertor(BinaryOperator<Integer> binaryOperator) {
return binaryOperator.apply(60, 72);
}
public static void main(String[] args) {
LambdaTest test = new LambdaTest();
BinaryOperator<Integer> binaryOperator = (a, b) -> a*b;
System.out.println("Additon using Lambda BinaryOperator: "+test.lambdaBinaryOpertor(binaryOperator));
}
}
Run Code Online (Sandbox Code Playgroud)
在这个文章,他们关于如何编译的lambda表达式转换成字节码讨论.根据该文档,lambda表达式转换为static方法和lambda表达式声明的位置,具有lambda static方法的引用.以下示例位于文章中:
//Source code
class A {
public void foo() {
List<String> list = ...
list.forEach( s -> { System.out.println(s); } );
}
}
//After compile above code "translate code "
class A {
public …Run Code Online (Sandbox Code Playgroud) SpliteratorJava 8中的类有什么好的用例场景?
假设我有一个单词列表,我想创建一个方法,将新列表的大小作为参数并返回新列表.如何从原始sourceList中获取随机单词?
public List<String> createList(int listSize) {
Random rand = new Random();
List<String> wordList = sourceWords.
stream().
limit(listSize).
collect(Collectors.toList());
return wordList;
}
Run Code Online (Sandbox Code Playgroud)
那么我如何以及在哪里使用我的随机数?
我尝试命名一个lambda参数_,例如(一个减少版本):
Consumer<Object> c = _ -> {};
Run Code Online (Sandbox Code Playgroud)
因为我想表示一个参数被忽略,但我得到了以下编译器错误:
对于lambda参数禁止使用'_'作为标识符
这对我来说是一个惊喜.有趣的是,两个下划线是可以的:
Consumer<Object> c = __ -> {}; // no compile error
Run Code Online (Sandbox Code Playgroud)
因此,它不是一般的下划线字符,而是单个字符.
为什么单下划线名称是专门禁止的?
我正在尝试使用一个IntStream实例化对象流:
Stream<MyObject> myObjects =
IntStream
.range(0, count)
.map(id -> new MyObject(id));
Run Code Online (Sandbox Code Playgroud)
但它说它无法转换MyObject为int.
在查看一些分析结果时,我注意到在紧密循环中使用流(使用而不是另一个嵌套循环)会导致类型java.util.stream.ReferencePipeline和对象的大量内存开销java.util.ArrayList$ArrayListSpliterator.我将有问题的流转换为foreach循环,并且内存消耗显着下降.
我知道溪流没有做出比普通环更好的表现的承诺,但我的印象是差异可以忽略不计.在这种情况下,似乎增加了40%.
这是我编写的用于隔离问题的测试类.我使用JFR监视内存消耗和对象分配:
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Predicate;
public class StreamMemoryTest {
private static boolean blackHole = false;
public static List<Integer> getRandListOfSize(int size) {
ArrayList<Integer> randList = new ArrayList<>(size);
Random rnGen = new Random();
for (int i = 0; i < size; i++) {
randList.add(rnGen.nextInt(100));
}
return randList;
}
public static boolean getIndexOfNothingManualImpl(List<Integer> nums, Predicate<Integer> predicate) {
for (Integer num : nums) {
// Impossible condition
if (predicate.test(num)) {
return true; …Run Code Online (Sandbox Code Playgroud) 我有两个数字列表,我想找到所有可能的数字对.例如,给定列表[1,2,3]和[3,4],结果应该是[(1,3),(1,4),(2,3),(2,4),(3) ,3),(3,4)].
我知道我可以使用for循环来做到这一点,但有没有更简洁的方法来使用Java 8流?
我试过以下但是我错过了一些东西,因为我得到了List<Stream<int[]>>而不是List<int[]>.
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(3, 4);
List<int[]> pairs = list1.stream().map(i -> list2.stream().map(j -> new int[] { i, j }))
.collect(Collectors.toList());
pairs.forEach(i -> {
System.out.println("{" + i[0]+ "," + i[1]+ "}");
});
}
Run Code Online (Sandbox Code Playgroud) 我想转换我看起来像这样的地图:
{
key="someKey1", value=Apple(id="1", color="green"),
key="someKey2", value=Apple(id="2", color="red"),
key="someKey3", value=Apple(id="3", color="green"),
key="someKey4", value=Apple(id="4", color="red"),
}
Run Code Online (Sandbox Code Playgroud)
到另一个地图,将所有相同颜色的苹果放入同一个列表中:
{
key="red", value=list={apple1, apple3},
key="green", value=list={apple2, apple4},
}
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法:
Map<String, Set<Apple>> sortedApples = appleMap.entrySet()
.stream()
.collect(Collectors.toMap(l -> l.getColour, ???));
Run Code Online (Sandbox Code Playgroud)
我是在正确的轨道上吗?我应该使用过滤器来执行此任务吗?有没有更简单的方法?
java ×10
java-8 ×10
lambda ×6
java-stream ×5
eclipselink ×1
iterator ×1
jvm ×1
memory ×1
spliterator ×1
timertask ×1
underscores ×1