67329


Java8,非同期処理の勉強をしていてCompletionStageクラスの勉強をしています。

質問の結論としては、 **コンパイルエラーを解決したいです。**

以下のサイトのサンプルプログラムを実際に動かしています。  
<https://www.kannon.link/fuku/index.php/2016/11/06/01-19/>

[code]

    package java8;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.math.BigDecimal;
    import java.net.URL;
    import java.util.concurrent.CompletableFuture;
    import java.util.stream.Stream;
    
    public class Main {
    
        public static void main(String[] args) {
            // TODO 自動生成されたメソッド・スタブ
            System.out.println(Thread.currentThread().getName() + ": main() started.");
            //Googleの株価
            CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> downloadStockInfo("GOOG"))
                    .thenApply(Main::extractClosePrices)
                    .thenAccept(Main::printAveragePrice);
            //Amazonの株価
            CompletableFuture cf2 = CompletableFuture.supplyAsync(() -> downloadStockInfo("AMZN"))
                    .thenApply(Main::extractClosePrices)
                    .thenAccept(Main::printAveragePrice);
            //Appleの株価
            CompletableFuture cf3 = CompletableFuture.supplyAsync(() -> downloadStockInfo("AAPL"))
                    .thenApply(Main::extractClosePrices)
                    .thenAccept(Main::printAveragePrice);
            System.out.println(Thread.currentThread().getName() + ": main() running.");
            cf1.get();
            cf2.get();
            cf3.get();
            System.out.println(Thread.currentThread().getName() + ": main() end.");
        }
    
        /**
         * YahooファイナンスのURLから指定した銘柄の数年分の株価情報を取得する
         * @param ticker 銘柄のID
         * @return 株価情報テーブル
         */
        private static Stream downloadStockInfo(final String ticker) {
            try {
                URL url = new URL("https://ichart.finance.yahoo.com/table.csv?s=" + ticker);
                BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
                System.out.println(Thread.currentThread().getName() + ": downloadStockInfo() executed. ticker " + ticker);
                return reader.lines();
            } catch(Exception ex) {
                throw new RuntimeException(ex);
            }
        }
    
        /**
         * 株価情報テーブルから終値を抽出する
         * @param stockInfo 株価情報テーブル
         * @return 株価情報テーブルから抽出した終値
         */
        private static Stream extractClosePrices(Stream stockInfo) {
            Stream closePricesStr = stockInfo.skip(1).map(x -> x.split(",")[4]);
            Stream closePrices = closePricesStr.map(BigDecimal::new);
            System.out.println(Thread.currentThread().getName() + ": getClosePrice() executed.");
            return closePrices;
        }
    
        /**
         * 終値の平均値を計算し出力する
         * @param closePrices 終値の数年分のリスト
         */
        private static void printAveragePrice(Stream closePrices){
            Double average = closePrices.mapToDouble(BigDecimal::doubleValue).average().getAsDouble();
            System.out.println(Thread.currentThread().getName() + ": printAveragePrice() executed. avg " + average + ".");
        }
    
    }
    
[/code]

ただしコンパイルエラーがおきました。  
[![画像の説明をここに入力](https://i.stack.imgur.com/MUsML.png)](https://i.stack.imgur.com/MUsML.png)

[code]

    説明  リソース    パス  ロケーション  型
    The type BigDecimal does not define BigDecimal(Object) that is applicable here  Main.java   /lucene/src/main/java8  行 57    Java 問題
    The type BigDecimal does not define doubleValue(Object) that is applicable here Main.java   /lucene/src/main/java8  行 67    Java 問題
    メソッド split(String) は型 Object で未定義です Main.java   /lucene/src/main/java8  行 56    Java 問題
    型 Stream のメソッド map(Function) は引数 (BigDecimal::new) に適用できません Main.java   /lucene/src/main/java8  行 57    Java 問題
    型 Stream のメソッド mapToDouble(ToDoubleFunction) は引数 (BigDecimal::doubleValue) に適用できません Main.java   /lucene/src/main/java8  行 67    Java 問題
    
[/code]

なぜこのエラーが起きているか調べているのですが、まだ解決に至っていません。

エラーメッセージで検索をかけたり、BigDecimalやメソッド参照について調べました。

もしわかる方がいればお願いいたします。


CC BY-SA 4.0
2020-06-05T05:01:53.473
67315
2020-06-05T10:09:51.723
2020-06-05T05:28:17.803
40231
40231
question
java eclipse java8
CompletionStageのサンプルプログラムのエラーを解決したい


[ジェネリクス(総称型)](https://docs.oracle.com/javase/jp/7/technotes/guides/language/generics.html)に関するコードの問題です。エラーだけでなく、(その下に表示されている)警告の内容も見てみてください。

* * *

例えば

[code]

    private static void printAveragePrice(Stream closePrices){
        Double average = closePrices.mapToDouble(BigDecimal::doubleValue).average().getAsDouble();
        ...
    }
    
[/code]

の `closePrices.mapToDouble(BigDecimal::doubleValue)`
の部分ですが、[`mapToDouble`のリファレンス](https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/stream/Stream.html#mapToDouble\(java.util.function.ToDoubleFunction\))を見ると

[code]

    DoubleStream mapToDouble​(ToDoubleFunction<? super T> mapper)
    
[/code]

とあるかと思います。  
ここで登場している`T`は(上記リンク先のページ冒頭にある通り)`Stream`インタフェースの型パラメータであり「ストリーム要素の型」を表しますが、今回のコードでは指定されていません(`closePrices`は`Stream`型として宣言されており、パラメータ化されていない)。  
このため`closePrices.mapToDouble`メソッドの引数に指定するものは`Object`型全般を`double`に変換できる必要があります(言わば`ToDoubleFunction<Object>`型)が、今回のコードで指定されている
`BigDecimal::doubleValue` は(言わば) `ToDoubleFunction<BigDecimal>` 型であり、型が異なります。

* * *

コンパイルエラーを解消するには、型パラメータを明記します。上記のコードでいうと、

[code]

    private static void printAveragePrice(Stream<BigDecimal> closePrices){
        ...
    }
    
[/code]

というように、 `closePrices`を(`Stream`型ではなく)`Stream<BigDecimal>`型として宣言します。

[コード差分](https://github.com/yukihane/stackoverflow-
qa/commit/59bfdb02d5963210d9df372e622dc2da7b8c215c)


CC BY-SA 4.0
2020-06-05T10:01:41.980
67329
2020-06-05T10:09:51.723
2020-06-05T10:09:51.723
2808
2808
67315
answer