我编写了以下代码,用于查找某些预算中的漫画 pageCount 。
起初我试图提出具有这样的架构的代码:
由于我无法设计一种编写代码的方法,就像我在上面的步骤中提到的那样,我采用了反应式编程的命令式编程。结果我写了下面的代码:
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");
}
});
我的预订:
map(), scan()
内创建一个新的Hashmap是个好主意吗?的问题:
此代码在onError
中提供 NullPointerException ,因为map.get("price")
在scan()
中返回null。我不确定原因。
错误:
onError java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference
注意:
HashMap不为null,由于某种原因,double字段将返回NULL。我正在试图弄清楚如何。
答案 0 :(得分:2)
由于
,您可能会遇到一个空的初始地图.scan(new HashMap<String, Double>(), ...)
当第一张真实地图从上游到达时,您正试图从该空白初始地图中获取值:
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.
答案 1 :(得分: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);
}
答案 2 :(得分: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();
方法
答案 3 :(得分: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 具有 价格和页数 的值, 当您将 pageCount 添加为 comicCount 我认为您缺少 comicCount 地图 ,
中的em>我建议使用try catch并打印错误以了解根本原因