从 ArrayList 创建 TreeSet 时导致 NPE 的原因是什么?
What is causing NPE when creating TreeSet from ArrayList?
我正在开发一个使用 CDI 事件的 JEE 应用程序。
WildFly Full 12.0.0.Final (WildFly Core 4.0.0.Final)
jdk1.8.0_121
[org.jboss.weld.Version] (MSC service thread 1-2) WELD-000900: 3.0.3 (Final)
我在一些事件中传递数据。
事件class我遇到困难的是这个:-
public class KeywordPersist implements Serializable {
private static final long serialVersionUID = 1L;
private final String doi;
private final List<String> keywords = new ArrayList<>();
public KeywordPersist(final String doi, final List<String> keywords) {
super();
this.doi = doi;
this.keywords.clear();
this.keywords.addAll(keywords);
}
//Getters, Setters, Hashcode, equals, toString NOT shown
}
我使用这个class如下:-
我将其注入无状态 EJB
@Inject
Event<KeywordPersist> keywordPersistEvent;
我只在数据存在时触发事件:-
if ((result.getKeywordList() == null) || (result.getKeywordList().getKeyword() == null) || result.getKeywordList().getKeyword().isEmpty()) {
return;
}
keywordPersistEvent.fire(generateKeywordEvent(result));
我生成的事件数据如下:-
private KeywordPersist generateKeywordEvent(final Result result) {
final KeywordPersist keywordPersist = new KeywordPersist(result.getDoi(), new ArrayList<String>(result.getKeywordList().getKeyword()));
return keywordPersist;
}
我对这个事件的观察者是另一个无状态 EJB:-
@Asynchronous
@Transactional(TxType.REQUIRES_NEW)
@Lock(LockType.WRITE)
public void parse(@Observes final KeywordPersist keywordPersist) {
persistDoiKeyword(keywordPersist);
}
持久化方法类似于:-
我想要独特的关键字,所以我从事件中传递的关键字 ArrayList 创建了一个 TreeSet
/**
*
* @param result
*/
private void persistDoiKeyword(final KeywordPersist keywordPersist) {
if (keywordPersist == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist == null) {}");
throw new RuntimeException("Never can happen 0000");
}
if (keywordPersist.getDoi() == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getDoi() == null) {}");
throw new RuntimeException("Never can happen 0001");
}
if (keywordPersist.getKeywords() == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getKeywords()== null) {}");
throw new RuntimeException("Never can happen 0002");
}
if (keywordPersist.getKeywords().isEmpty()) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getKeywords().isEmpty()) {}");
throw new RuntimeException("Never can happen 0003");
}
final Set<String> uniqueKeywordsSet = new TreeSet<>(keywordPersist.getKeywords());
final List<String> uniqueKeywords = new ArrayList<>(uniqueKeywordsSet);
long rowCount = 0;
for (String keyword : uniqueKeywords) {
final DoiKeyword doiKeyword = new DoiKeyword();
doiKeyword.setKeywordDoi(keywordPersist.getDoi());
doiKeyword.setKeyword(cleanse(keyword));
entityManager.persist(doiKeyword);
rowCount++;
if ((rowCount % 20) == 0) {
entityManager.flush();
entityManager.clear();
}
}
entityManager.flush();
entityManager.clear();
}
我得到的异常是...
Caused by: java.lang.NullPointerException
at java.util.TreeMap.put(TreeMap.java:563)
at java.util.TreeSet.add(TreeSet.java:255)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.TreeSet.addAll(TreeSet.java:312)
at java.util.TreeSet.<init>(TreeSet.java:160)
at com.research.events.observers.KeywordPersistObserver.persistDoiKeyword(KeywordPersistObserver.java:66)
at com.research.events.observers.KeywordPersistObserver.parse(KeywordPersistObserver.java:37)
at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:509)
当我使用 TreeSet 时,为什么在堆栈跟踪中提到 TreeMap?
这个 NPE 来自哪里?
在使用自然顺序的 TreeSet
中不允许 null
引用。这是 String 的 TreeSet 的情况。
TreeSet.add(E e)
由 TreeSet
构造函数在后台使用确实指定:
Throws:
...
NullPointerException
- if the specified element is null and this set
uses natural ordering, or its comparator does not permit null elements
作为解决方法,您可以创建一个既依赖于 String.compareTo()
又接受 null
值的比较器。
例如,要将 null
引用排名为较低的元素,您可以实例化您的 TreeSet,例如:
TreeSet<String> set = new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder());
我正在开发一个使用 CDI 事件的 JEE 应用程序。
WildFly Full 12.0.0.Final (WildFly Core 4.0.0.Final)
jdk1.8.0_121
[org.jboss.weld.Version] (MSC service thread 1-2) WELD-000900: 3.0.3 (Final)
我在一些事件中传递数据。
事件class我遇到困难的是这个:-
public class KeywordPersist implements Serializable {
private static final long serialVersionUID = 1L;
private final String doi;
private final List<String> keywords = new ArrayList<>();
public KeywordPersist(final String doi, final List<String> keywords) {
super();
this.doi = doi;
this.keywords.clear();
this.keywords.addAll(keywords);
}
//Getters, Setters, Hashcode, equals, toString NOT shown
}
我使用这个class如下:-
我将其注入无状态 EJB
@Inject
Event<KeywordPersist> keywordPersistEvent;
我只在数据存在时触发事件:-
if ((result.getKeywordList() == null) || (result.getKeywordList().getKeyword() == null) || result.getKeywordList().getKeyword().isEmpty()) {
return;
}
keywordPersistEvent.fire(generateKeywordEvent(result));
我生成的事件数据如下:-
private KeywordPersist generateKeywordEvent(final Result result) {
final KeywordPersist keywordPersist = new KeywordPersist(result.getDoi(), new ArrayList<String>(result.getKeywordList().getKeyword()));
return keywordPersist;
}
我对这个事件的观察者是另一个无状态 EJB:-
@Asynchronous
@Transactional(TxType.REQUIRES_NEW)
@Lock(LockType.WRITE)
public void parse(@Observes final KeywordPersist keywordPersist) {
persistDoiKeyword(keywordPersist);
}
持久化方法类似于:-
我想要独特的关键字,所以我从事件中传递的关键字 ArrayList 创建了一个 TreeSet
/**
*
* @param result
*/
private void persistDoiKeyword(final KeywordPersist keywordPersist) {
if (keywordPersist == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist == null) {}");
throw new RuntimeException("Never can happen 0000");
}
if (keywordPersist.getDoi() == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getDoi() == null) {}");
throw new RuntimeException("Never can happen 0001");
}
if (keywordPersist.getKeywords() == null) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getKeywords()== null) {}");
throw new RuntimeException("Never can happen 0002");
}
if (keywordPersist.getKeywords().isEmpty()) {
System.out.println("---------------------------- persistDoiKeyword() if (keywordPersist.getKeywords().isEmpty()) {}");
throw new RuntimeException("Never can happen 0003");
}
final Set<String> uniqueKeywordsSet = new TreeSet<>(keywordPersist.getKeywords());
final List<String> uniqueKeywords = new ArrayList<>(uniqueKeywordsSet);
long rowCount = 0;
for (String keyword : uniqueKeywords) {
final DoiKeyword doiKeyword = new DoiKeyword();
doiKeyword.setKeywordDoi(keywordPersist.getDoi());
doiKeyword.setKeyword(cleanse(keyword));
entityManager.persist(doiKeyword);
rowCount++;
if ((rowCount % 20) == 0) {
entityManager.flush();
entityManager.clear();
}
}
entityManager.flush();
entityManager.clear();
}
我得到的异常是...
Caused by: java.lang.NullPointerException
at java.util.TreeMap.put(TreeMap.java:563)
at java.util.TreeSet.add(TreeSet.java:255)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at java.util.TreeSet.addAll(TreeSet.java:312)
at java.util.TreeSet.<init>(TreeSet.java:160)
at com.research.events.observers.KeywordPersistObserver.persistDoiKeyword(KeywordPersistObserver.java:66)
at com.research.events.observers.KeywordPersistObserver.parse(KeywordPersistObserver.java:37)
at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at org.jboss.invocation.InterceptorContext$Invocation.proceed(InterceptorContext.java:509)
当我使用 TreeSet 时,为什么在堆栈跟踪中提到 TreeMap?
这个 NPE 来自哪里?
TreeSet
中不允许 null
引用。这是 String 的 TreeSet 的情况。
TreeSet.add(E e)
由 TreeSet
构造函数在后台使用确实指定:
Throws:
...
NullPointerException
- if the specified element is null and this set uses natural ordering, or its comparator does not permit null elements
作为解决方法,您可以创建一个既依赖于 String.compareTo()
又接受 null
值的比较器。
例如,要将 null
引用排名为较低的元素,您可以实例化您的 TreeSet,例如:
TreeSet<String> set = new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder());