OneError java.lang.NullPointerException:尝试调用虚拟方法';double java.lang.double.doubleValue()';关于空对象引用

OneError java.lang.NullPointerException:尝试调用虚拟方法';double java.lang.double.doubleValue()';关于空对象引用,java,android,rx-java,observable,rx-android,Java,Android,Rx Java,Observable,Rx Android,我编写了以下代码,用于查找在一定预算范围内的漫画页面数 起初,我试图提出具有如下体系结构的代码: 流给出了一个对象的价格 我将MarvelComic对象从流中的价格与之前在此流中的漫画价格相加,并检查其是否符合预算 如果是,则我将MarvelComic对象的pageCount与流中先前MarvelComic对象的pageCount之和相加 如果是,则调用订户的onNext 由于我无法设计出一种像上面步骤中提到的那样编写代码的方法,所以我求助于将命令式编程与反应式编程混为一谈。因此,我编写了以

我编写了以下代码,用于查找在一定预算范围内的漫画页面数

起初,我试图提出具有如下体系结构的代码:

  • 流给出了一个对象的价格
  • 我将MarvelComic对象从流中的价格与之前在此流中的漫画价格相加,并检查其是否符合预算
  • 如果是,则我将MarvelComic对象的pageCount与流中先前MarvelComic对象的pageCount之和相加
  • 如果是,则调用订户的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");
                    }
                });
注意:

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

HashMap不是null,由于某种原因,double字段返回为null。我正在尝试找出方法。

我认为可以获得
getPrice(),getPageCount()方法的null或空白值

 map.put("price", Double.valueOf(marvelComic.getPrice()));
                            map.put("pageCount", Double.valueOf(marvelComic.getPageCount()));
                            map.put("comicCount", Double.valueOf(marvelComic.getPageCount()));
或者可以使用
Double.parseDouble()方法

您在这里已经使用了三次doubleValue()函数

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


我建议使用try-catch并打印错误以了解根本原因

问题可能是由于

.scan(new HashMap<String, Double>(), ...)
我假设您希望通过使用
scan
对属性进行运行聚合,因此您应该尝试
scan(双功能)
,按原样发出第一个上游值,然后开始将前一个值与新的上游值相结合

或者,您可以使用默认值预先初始化
新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.
HashMap initialMap=newhashmap();
初始映射。放置(“价格”,0.0d);
初始映射放置(“页面计数”,0.0d);
初始映射放置(“ComAccount”,0.0d);
Observable.fromIterable(getMarvelComicsList())。
映射(新函数(){
@凌驾
公共哈希映射应用(@NonNull){
HashMap=newHashMap();
map.put(“price”,Double.valueOf(mavelcomic.getPrice());
put(“pageCount”,Double.valueOf(marvelComic.getPageCount());
map.put(“ComAccount”,Double.valueOf(marvelComic.getPageCount());
返回图;
}
})
.scan(初始化映射,
新的双函数(){
@凌驾
公共哈希映射应用(
@非空HashMap inputMap,
@非空HashMap(newValueMap){
双和=inputMap.get(“价格”)+newValueMap.get(“价格”);
double count=inputMap.get(“页面计数”)
+获取(“页面计数”);
double ComAccount=inputMap.get(“ComAccount”)
+获取(“ComAccount”);
HashMap=newHashMap();
map.put(“价格”,总和);
map.put(“pageCount”,count);
地图放置(“ComAccount”,ComAccount);
返回图;
}
})
//等等。

我尝试用一种不同的方法来解决您的问题,这种方法不会引发任何NPE

请不要将哈希映射用作数据结构。正在发生的事情是不容忽视的。您应该创建有意义的类

此外,订户不应执行任何业务逻辑。订阅者实际上应该只使用结果,并做一些副作用,如更改视图

我希望我正确理解了你的问题

@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);
}
@测试
无效名称(){
ArrayList marvelComics=List.newArrayList(新惊奇漫画(10200)、新惊奇漫画(3133)、新惊奇漫画(5555)、新惊奇漫画(32392));
最终双预算=20.0;
可观测结果可观测=可观测。可观测(惊奇漫画)
.scan(Result.IDENTITY,(Result,manvelcomic)->{
double priceSum=result.sumPrice+marvelComic.getPrice();
if(priceSum result!=result.IDENTITY);
TestObserver test=resultObservable.test().assertValueCount(3);
结果result1=test.values()
.stream()
.reduce((结果,结果2)->result2)
.get();
资产(结果1.ComicAccount)。isEqualTo(3);
资产(result1.sumPageCount).isEqualTo(888);
资产(结果1.sumPrice)。isEqualTo(18);
}
班级漫画{
私人最终双倍价格;
私人最终整版页数;
惊奇漫画(双倍价格,整数页数){
这个价格=价格;
this.pageCount=pageCount;
}
公开双价{
退货价格;
}
public int getPageCount(){
返回页面计数;
}
}
静态类结果{
私人最终int sumPageCount;
私人最终双重价格;
私人最终国际帐户;
结果(int sumPageCount、双sumPrice、int COMICOUNT){
this.sumPageCount=sumPageCount;
this.sumPrice=sumPrice;
this.comicCount=comicCount;
}
静态结果标识=新结果(0,0,0);
}

为什么不使用一个带有
字段和两个
int
字段的类来代替
HashMap
?是的,我想到了这一点,但我认为使用集合而不是创建单独的类将是一个更干净的解决方案。即使我创建了另一个类,我也必须创建该类的对象
@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);
}