2017-04-25 55 views
0

我已經編寫了以下代碼,用於查找pageCount位於特定內的漫畫預算onError java.lang.NullPointerException:嘗試調用空對象引用上的虛擬方法'double java.lang.Double.doubleValue()'

起初,我試着拿出代碼,將有架構是這樣的:

  • 流給人MarvelComic對象的價格。
  • 我與以前的漫畫的價格是降下來此流求和MarvelComic對象的價格從流並檢查它是否是< 預算
  • 如果是,那麼我總結了頁頁次 MarvelComic對象與之前的pageCount之和MarvelComic對象下來的流。
  • 如果是,則調用訂戶的onNext

因爲我無法想出像上述步驟中提到的那樣編寫代碼的方法,所以我使用了無功編程的糖化命令編程。因此,我寫了下面的代碼:

Observable.fromIterable(getMarvelComicsList()). 
       map(new Function<MarvelComic, HashMap<String, Double>>() { 
        @Override 
        public HashMap<String, Double> apply(@NonNull MarvelComic marvelComic) throws Exception { 
         HashMap<String, Double> map = new HashMap<String, Double>(); 
         map.put("price", Double.valueOf(marvelComic.getPrice())); 
         map.put("pageCount", Double.valueOf(marvelComic.getPageCount())); 
         map.put("comicCount", Double.valueOf(marvelComic.getPageCount())); 
         return map; 
        } 
       }) 
       .scan(new HashMap<String, Double>(), new BiFunction<HashMap<String, Double>, HashMap<String, Double>, HashMap<String, Double>>() { 
        @Override 
        public HashMap<String, Double> apply(@NonNull HashMap<String, Double> inputMap, @NonNull HashMap<String, Double> newValueMap) throws Exception { 
         double sum = inputMap.get("price")+newValueMap.get("price"); 
         double count = inputMap.get("pageCount")+newValueMap.get("pageCount"); 
         double comicCount = inputMap.get("comicCount")+newValueMap.get("comicCount"); 

         HashMap<String, Double> map = new HashMap<String, Double>(); 
         map.put("price", sum); 
         map.put("pageCount", count); 
         map.put("comicCount", comicCount); 

         return map; 
        } 
       }) 
       .takeWhile(new Predicate<HashMap<String, Double>>() { 
        @Override 
        public boolean test(@NonNull HashMap<String, Double> stringDoubleHashMap) throws Exception { 
         return stringDoubleHashMap.get("price") < budget; 
        } 
       }) 
       .subscribe(new DisposableObserver<HashMap<String, Double>>() { 
        @Override 
        public void onNext(HashMap<String, Double> stringDoubleHashMap) { 
         double sum = stringDoubleHashMap.get("price"); 
         double pageCount = stringDoubleHashMap.get("pageCount"); 
         double comicCount = stringDoubleHashMap.get("comicCount"); 
         Timber.e("sum %s pageCount %s ComicCount: %s", sum, pageCount, comicCount); 
        } 

        @Override 
        public void onError(Throwable e) { 
         Timber.e("onError %s", e.fillInStackTrace()); 
        } 

        @Override 
        public void onComplete() { 
         Timber.e("onComplete"); 
        } 
       }); 

我的酒店預訂:

  1. 它是創建一個新的Hashmap內map(), scan()每次都好主意嗎?
  2. 如何進一步改進此代碼?

問題:

該代碼給出NullPointerException異常onError因爲map.get("price")回報scan()空。我不確定原因。

錯誤:

onError java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference 

注:

HashMap中不爲空,雙場被返回爲NULL出於某種原因。我試圖弄清楚如何。

+0

爲什麼不使用具有'double'字段和兩個'int'字段而不是'HashMap'的類? –

+0

是的,我想到了,但我認爲,而不是創建一個單獨的班級,訴諸收集將是一個更乾淨的解決方案。即使我創建了另一個班級,我也必須在精讀方法中創建該班級的一個對象。 –

+0

@DharmbirSingh請發表問題並停止評論與此問題無關的內容。 –

回答

1

這個問題可能是你有一個空的初始地圖由於

,當第一個真正的地圖從上游到達時,你正試圖從空的初始地圖中獲取值:

double sum = inputMap.get("price")+newValueMap.get("price"); 

我假設你想通過使用scan做一個運行聚合的屬性,所以你應該嘗試scan(BiFunction),它會發出第一個上游值,然後開始將上一個值與新的上游值組合起來。

或者,你可以預先初始化new HashMap<>()用默認值,避免NPE還有:

HashMap<String, Double> initialMap = new HashMap<String, Double>(); 
initialMap.put("price", 0.0d); 
initialMap.put("pageCount", 0.0d); 
initialMap.put("comicCount", 0.0d); 

Observable.fromIterable(getMarvelComicsList()). 
      map(new Function<MarvelComic, HashMap<String, Double>>() { 
       @Override 
       public HashMap<String, Double> apply(@NonNull MarvelComic marvelComic) { 
        HashMap<String, Double> map = new HashMap<String, Double>(); 
        map.put("price", Double.valueOf(marvelComic.getPrice())); 
        map.put("pageCount", Double.valueOf(marvelComic.getPageCount())); 
        map.put("comicCount", Double.valueOf(marvelComic.getPageCount())); 
        return map; 
       } 
      }) 
      .scan(initialMap, 
      new BiFunction<HashMap<String, Double>, 
        HashMap<String, Double>, HashMap<String, Double>>() { 
       @Override 
       public HashMap<String, Double> apply(
         @NonNull HashMap<String, Double> inputMap, 
         @NonNull HashMap<String, Double> newValueMap) { 
        double sum = inputMap.get("price")+newValueMap.get("price"); 
        double count = inputMap.get("pageCount") 
         +newValueMap.get("pageCount"); 
        double comicCount = inputMap.get("comicCount") 
         +newValueMap.get("comicCount"); 

        HashMap<String, Double> map = new HashMap<String, Double>(); 
        map.put("price", sum); 
        map.put("pageCount", count); 
        map.put("comicCount", comicCount); 

        return map; 
       } 
      }) 
      // etc. 
+0

非常感謝。這正是我做錯了。但是,請你告訴我在什麼情況下,一個人會使用scan(initialize,new BiFunc()...)''? 另一個問題是,使用集合在多個字段上執行操作的方式是否好?還是應該爲所有屬性編寫單獨的可觀察值並將其壓縮?我不知道這個zip()的東西是否會起作用(仍然是新手),但是那個效率低下的IMO我會得到N個可觀察的數據,而且我將在N個字段上重複N次。 –

+1

即使上游爲空也需要初始值。屬於一起的價值觀應該一起旅行,沒有太多理由將它們分開放入它們自己的流中,當它們一起可用時。 Hans應該考慮使用適當的值類而不是HashMap。 – akarnokd

+0

@Thanks我爲這個過濾過程創建了一個單獨的Model類。我一直都很不願意爲每個流程創建單獨的模型類,而不是使用集合。其他模型課堂只是在我看來產生了噪音,但隨後考慮到我有限的知識,可能創建模型課程是最佳途徑。 –

0

我認爲你可以得到的getPrice(),getPageCount()方法

map.put("price", Double.valueOf(marvelComic.getPrice())); 
          map.put("pageCount", Double.valueOf(marvelComic.getPageCount())); 
          map.put("comicCount", Double.valueOf(marvelComic.getPageCount())); 

,或者您可以使用Double.parseDouble();方法null或空白值

+0

否這些值不爲空或爲空。我將它們插入到散列圖中之前雙重檢查了值 –

+0

可以試試Double.parseDouble();方法 –

0

您使用的doubleValue()函數在這裏3次,

map.put("price", Double.valueOf(marvelComic.getPrice())); 
map.put("pageCount", Double.valueOf(marvelComic.getPageCount())); 
map.put("comicCount", Double.valueOf(marvelComic.getPageCount())); 

確認marvelComic has t他爲價格和頁數, 我認爲你缺少comicCount因爲你是在地圖加入頁頁次comicCount

我會建議使用try catch並打印錯誤以瞭解根本原因

+0

我在問題中提到MarvelComic有值 –

+0

你能發佈MarvelComic的代碼嗎 – SwapnilKumbhar

1

我試着用不同的方法,它不拋出任何NPE解決您的問題。

請不要使用HashMaps作爲數據結構。這是不透明的。你應該創建有意義的類。

此外,用戶不應該做任何businesslogic。用戶實際上應該只是使用結果,並改變視圖等副作用。

我希望我確實理解了你的問題。

@Test 
void name() { 
    ArrayList<MarvelComic> marvelComics = Lists.newArrayList(new MarvelComic(10, 200), new MarvelComic(3, 133), new MarvelComic(5, 555), new MarvelComic(32, 392)); 

    final double BUDGET = 20.0; 

    Observable<Result> resultObservable = Observable.fromIterable(marvelComics) 
      .scan(Result.IDENTITY, (result, marvelComic) -> { 
       double priceSum = result.sumPrice + marvelComic.getPrice(); 

       if (priceSum <= BUDGET) { 
        int pageCount = result.sumPageCount + marvelComic.getPageCount(); 
        int comicCount = result.comicCount + 1; 
        return new Result(pageCount, priceSum, comicCount); 
       } 

       return Result.IDENTITY; 
      }) 
      .skip(1) // because first Value would be Result.IDENTITY 
      .takeWhile(result -> result != Result.IDENTITY); 

    TestObserver<Result> test = resultObservable.test().assertValueCount(3); 

    Result result1 = test.values() 
      .stream() 
      .reduce((result, result2) -> result2) 
      .get(); 

    assertThat(result1.comicCount).isEqualTo(3); 
    assertThat(result1.sumPageCount).isEqualTo(888); 
    assertThat(result1.sumPrice).isEqualTo(18); 
} 

class MarvelComic { 
    private final double price; 
    private final int pageCount; 

    MarvelComic(double price, int pageCount) { 
     this.price = price; 
     this.pageCount = pageCount; 
    } 

    public double getPrice() { 
     return price; 
    } 

    public int getPageCount() { 
     return pageCount; 
    } 
} 

static class Result { 
    private final int sumPageCount; 

    private final double sumPrice; 

    private final int comicCount; 

    Result(int sumPageCount, double sumPrice, int comicCount) { 
     this.sumPageCount = sumPageCount; 
     this.sumPrice = sumPrice; 
     this.comicCount = comicCount; 
    } 

    static Result IDENTITY = new Result(0, 0, 0); 
} 
+0

可否請您告訴我爲什麼HashMap會返回null來代替值,即使我自己將值放入其中,我又仔細檢查了它? –

+0

看@akarnokd的答案。掃描將空的hashMap推送給訂戶。如果元素不在hashMap中,Get將返回null。您嘗試在空返回時調用一個方法。請注意get方法的描述:返回: 指定鍵映射到的值;如果此映射不包含鍵的映射,則返回null –

相關問題