質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.47%

  • Java

    14142questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • CSV

    677questions

    CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

ソートしたデータの抽出方法を教えてください。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 883

lena

score 22

JAVA初心者です。 
月別の売上金額の大きい3商品を出力するプログラムを
作成しています。

【完成例】
商品名,数量 ,売上金額 ,備考
201601月売上高BEST3
バナナ,10,100,
玉ねぎ,8,80,
トマト,6,60,
201602月売上高BEST3
バナナ,15,150,
玉ねぎ,14,140,
白菜,10,110,
商品マスタ未存在,,,
,,,日付に誤りがあります

【今現在】
商品名,数量 ,売上金額 ,備考
201601月売上高BEST3
カボチャ,10,100,
カボチャ,8,80,
カボチャ,6,60,
商品マスタ未存在,,,
,,,日付に誤りがあります

【仕様内容】 
売上明細をもとに商品マスタより商品名と単価を取得します。
売上金額の大きい商品の順に出力します(sortメソッドは使用しない)。
商品の出力まえに「yyyymm月売上高BEST3」を出力します。

【分からない点】
①並び替えをした商品名を抽出するにはどうすればよろしいでしょうか?
②2月のデータが出力されないのはどうしてでしょうか?
完成例を実現する方法を教えてください。
どうぞよろしくお願いいたします。

package lesson;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;

public class MonthlySalesBest3 {

    public static void main(String[] args) {

        BufferedReader brM = null ; //商品マスタ入力ファイル
        BufferedReader brA = null ; //売上明細入力ファイル
        BufferedWriter bwA = null ;  //月額売上表出力ファイル
        String stM = ""; //inMファイルデータを格納
        String stA = ""; //inAファイルデータを格納
        HashMap<String,HashMap<String,Object>> alDM = new HashMap<String,HashMap<String,Object>>() ; //商品マスタの入力データを格納
        HashMap<String, Object> mpDM = null;
        String[] itemM ;  //inMファイルデータを配列に格納
        String[] itemA;   //inAファイルデータを配列に格納
        String date = ""; //売上明細ファイルの購入月をセット
        boolean isFirst = true; //0番目の購入日をセットする為の変数
        int amt1 = 0; //バナナの合計数量
        int amt2 = 0; //玉ねぎの合計数量
        int amt3 = 0; //トマトの合計数量
        int amt4 = 0; //白菜の合計数量
        int amt5 = 0; //カボチャの合計数量
        int sum1= 0; //バナナの合計金額
        int sum2= 0; //玉ねぎの合計金額
        int sum3= 0; //トマトの合計金額
        int sum4= 0; //白菜の合計金額
        int sum5= 0; //カボチャの合計金額
        int allSum1= 0; //バナナの月の合計金額
        int allSum2= 0; //玉ねぎの月の合計金額
        int allSum3= 0; //トマトの月の合計金額
        int allSum4= 0; //白菜の月の合計金額
        int allSum5= 0; //カボチャの月の合計金額

        final String  noItem = "商品マスタ未存在";
        final String noCalendar = "日付に誤りがあります";
        boolean emptyflgM = false;  //商品マスタファイル空判定フラグ
        boolean emptyflgA = false; //売上明細入力ファイル空判定フラグ

    try{
            fileError:{

        try{
        brM = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/temp/Desktop/inM.csv"),"JISAutoDetect"));
        }catch(FileNotFoundException e){
            System.err.println("inM.csvファイルが見つかりません。");
        }
        try{
        brA = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/temp/Desktop/inA.csv"),"JISAutoDetect"));
        }catch(FileNotFoundException e){
            System.err.println("inA.csvファイルが見つかりません。");
        }
        try{
        bwA = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:/Users/temp/Desktop/outA.csv"),"SJIS"));
        }catch(FileNotFoundException e){
            System.err.println("outA.csvファイルが見つかりません。");
        }

            //inMファイルデータを読み込み

            while((stM = brM.readLine()) != null){

                if(stM.equals("")){
                    System.err.println("データに不備があります。");
                    break fileError;
                }
                emptyflgM = true;

                itemM = stM.split(",");

                mpDM = new HashMap<String,Object>();

                mpDM.put("code",itemM[0]);
                mpDM.put("name",itemM[1]);
                mpDM.put("price",itemM[2]);

                alDM.put(itemM[0],mpDM);

            }//while
            if(emptyflgM == false){
                System.err.println("inMファイルが空です。");
                break fileError;
            }

            bwA.write("商品名" + "," + "数量" + " ," + "売上金額"  + " ," + "備考");
            bwA.newLine();

            try{

            while((stA = brA.readLine()) != null){

                if(stA.equals("")){
                    System.err.println("データに不備があります。");
                    break fileError;
                }
                emptyflgA = true;

                itemA = stA.split(",");

                mpDM = alDM.get(itemA[1]);

                if(isFirst){
                    date = itemA[0].substring(0, 6);
                    isFirst = false;
                }

                String soldDay = (itemA[0].substring(0, 6));

                int sold= soldDay.compareTo(date); //月変更の比較

                int[] allSums = {allSum1,allSum2,allSum3,allSum4,allSum5}; //全商品の月の合計金額を格納
                int[] amts = {amt1,amt2,amt3,amt4,amt5}; //全商品の月の合計数量を格納

                if(sold > 0){
                    bwA.write(date.substring(0, 6) + "月売上高BEST3"); //月売上高BEST3を出力
                    bwA.newLine();

                    for(int i=0; i<allSums.length-1; i++){ //売上金額を昇順に並べ替え
                        for(int j=i+1; j<allSums.length; j++){
                            if(allSums[i]<allSums[j]){
                                int temp=allSums[i];
                                allSums[i]=allSums[j];
                                allSums[j]=temp;
                            }
                        }
                    }

                    for(int i=0; i < 3; i++){

                        Object b = mpDM.get("name"); //商品名
                        int c = amts[i]; //数量
                        int d = allSums[i]; //数量
                        //Object d = mpDataM.get("price"); //単価

                        bwA.write(b + "," + c + "," + d + ",");
                        bwA.newLine();
                    }

                    date = itemA[0]; //売上日を再セット
                    amt1 = 0; //バナナの合計数量を0に戻す
                    amt2 = 0; //玉ねぎの合計数量を0に戻す
                    amt3 = 0; //トマトの合計数量を0に戻す
                    amt4 = 0; //白菜の合計数量を0に戻す
                    amt5 = 0; //カボチャの合計数量を0に戻す
                    sum1= 0; //バナナの合計金額を0に戻す
                    sum2= 0; //玉ねぎの合計金額を0に戻す
                    sum3= 0; //トマトの合計金額を0に戻す
                    sum4= 0; //白菜の合計金額を0に戻す
                    sum5= 0; //カボチャの合計金額
                    allSum1 = 0;  // バナナの月合計を0に戻す
                    allSum2 = 0;  // 玉ねぎの月合計を0に戻す
                    allSum3 = 0;  // トマトの月合計を0に戻す
                    allSum4 = 0;  // 白菜の月合計を0に戻す
                    allSum5 = 0;  // カボチャの月合計を0に戻す
                }

                if(alDM.containsKey(itemA[1])){

                    //String c = itemA[2]; //数量
                    String d = (String) mpDM.get("price"); //単価
                    String e = ""; //備考

                    if(checkDate(itemA[0])){ //日付の妥当性を確認

                        int num = Integer.parseInt(itemA[2]);
                        int num2 = Integer.parseInt((String) d);

                        switch (itemA[1]){
                          case "0001":
                              amt1 = amt1 + num;
                              sum1 = num * num2;
                              allSum1 = sum1 + allSum1;
                            //System.out.println(itemA[1]);
                            break;
                          case "0002":
                              amt2 = amt2 + num;
                              sum2 = num * num2;
                              allSum2 = sum2 + allSum2;
                               //System.out.println(itemA[1]);
                            break;
                          case "0003":
                              amt3 = amt3 + num;
                              sum3 = num * num2;
                              allSum3 = sum3 + allSum3;
                                //System.out.println(itemA[1]);
                            break;
                          case "0004":
                              amt4 = amt4 + num;
                              sum4 = num * num2;
                              allSum4 = sum4 + allSum4;
                                //System.out.println(itemA[1]);
                            break;
                          case "0005":
                              amt5 = amt5 + num;
                              sum5 = num * num2;
                              allSum5 = sum5 + allSum5;
                                //System.out.println(itemA[1]);
                            break;
                        }
                    } else{

                        e = noCalendar; //備考=日付に誤りがあります

                        bwA.write( "," + "," + "," + e);
                        bwA.newLine();
                    }

                }else{

                    //String a = itemA[0]; //購入日
                    Object b = noItem; //商品名=商品マスタ未存在
                    //String c = itemA[2]; //数量

                    bwA.write( b + "," + "," + ",");
                    bwA.newLine();

                }

            }//while
            if(emptyflgA == false){
                System.err.println("inA.csvファイルが空です。");
                break fileError;
            }

            }catch(IOException e){
                e.printStackTrace();
            }
        }//fileError

            }catch(FileNotFoundException e){
                System.err.println("ファイルが見つかりません。");
            }catch(IOException e){
                System.err.println("何らかのエラーが発生しました。");
            }
        finally{
            try {
                brA.close();
                brM.close();
                bwA.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}


        /**
         * 日付の妥当性をチェック
         * カレンダーに存在するかどうかを返す。
         * 存在する日付の場合true
         */
        public static boolean checkDate(String strDate) {
            if (strDate == null || strDate.length() != 8) {
                throw new IllegalArgumentException(
                        "引数の文字列["+ strDate +"]" +
                        "は不正です。");
            }

            DateFormat format = new SimpleDateFormat("yyyyMMdd");
            format.setLenient(false);
            try {
                format.parse(strDate);
                return true;
            } catch (Exception e) {
                return false;
            }
        }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

「mpDM = alDM.get(itemA[1]);」してるところで商品名を格納したMapを取ろうとしてるのはわかったけど、肝心の商品名を出力するとこ(「Object b = mpDM.get("name"); //商品名」)で同じmpDMを参照してるから同じ商品名が出るのです。

以下追記:

「並べ替えする数字」と「数字と対になる名前」は同じようにソートしてあげないとだめです。
金額・個数をセットにしてあれこれするのであれば、下のような独自クラスを作ってあげるのも手。

class Profit {
    /** 商品名 */
    public String itemName = null;
    /** 売上数量 */
    public int count = 0;
    /** 売上金額 */
    public int salesAmount = 0;
}


これを名前とセットで管理すれば同じように並べ替えができますよ。

HashMap<String, Profit> totalHolder = null;
// boolean isFirst = true;

while((stA = brA.readLine()) != null){

    itemA = stA.split(",");

    if(isFirst){
        date = itemA[0].substring(0, 6);
        isFirst = false;
    }

    String soldDay = (itemA[0].substring(0, 6));

    // 月変更の比較
    // 同じ月じゃなかったら今までため込んでた分を並べ替え&出力、でしょ?
    if(soldDay.equals(date) == false){
        // ここで並べ替え&出力:処理が長くなるのでさらに下の方で記述予定

        // totalHolderの初期化
        totalHolder = null;
    }

    if(totalHolder == null){
        totalHolder = new HashMap<String, Profit>();
    }

    mpDM = alDM.get(itemA[1]);
    //↑itemA[1]がなんなのかよくわかりませんが、ともあれこれでマスタが取れましたね。

    String itemName = mpDM.get("name");
    if(totalHolder.containsKey(itemName == false) { //totalHolderに名前が登録されてなければ新しく登録します。
        totalHolder.put(itemName, new Profit());
        totalHolder.get(itemName).itemName = itemName; // あとで値出力の時に使う
    }

    // これで数字の加算。
    totalHolder.get(itemName).count += 
    totalHolder.get(itemName).salesAmount += 

}


並べ替えの時にはMap#values()を使うとCollection型ですべての値が取得できるので、これをtoArray()してから並べ替えます。

Profit[] arr = totalHolder.values().toArray(new Profit[]);


後の並べ替え自体はProfit#salesAmountを比較していけばできますよね?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/23 16:11

    tkturboさん、ご回答ありがとうございます。
    なぜ同じ商品名が出力されるのか分かりましたが、どうすればソートされた商品名を抽出できるのか、いろいろと試しましたが結局分かりませんでした。
    よろしくお願いいたします。

    キャンセル

  • 2016/03/23 17:16

    長くなりそうだったので回答を編集しました。

    キャンセル

  • 2016/03/24 03:42

    tkturboさん、ご回答ありがとうございます。
    丁寧にご説明いただきありがとうございました。
    >「並べ替えする数字」と「数字と対になる名前」は同じようにソートしてあげないとだめです。
    確かにそうですね、気づきませんでした。
    ですがメソッド分割やクラスを分ける方法をまだ分からないので、ご説明いただいた内容をちゃんと理解するのは少々時間がかかりそうですが使いこなせるように頑張って勉強したいと思います。
    一つご質問があるのですが、並べ替えをソート機能を使わずロジックで考えて実装するにはどうすればよろしいでしょうか?
    お応えいただけると幸いです。

    キャンセル

  • 2016/03/24 09:23

    ロジックでのソート方法はこちらが詳しいので参考にしてください→ http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/

    キャンセル

  • 2016/03/25 13:25

    tkturboさん、教えて下さりありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    社員情報のプログラム

    社員情報のプログラム (JAVA) プログラの機能 (1)社員情報の追加 入力項目としては、社員番号、氏名(性、名)、生年月日(年、月、日) (3)で読み込んだ情報を追加する仕

  • 受付中

    このコードをスマートにしてください

    aをb乗するプログラムを作成しております。 前回の質問で回答していただいた方々のおかげでとりあえずやりたかった動作をしてくれるプログラムは完成しました。 しかしこのプログラムを

  • 解決済

    フォルダの中にあるファイルを1つずつ読み込む

    最近Javaで開発を始めました。 複数のファイルが入っているフォルダがあります。 このフォルダから1ファイルずつ開き中身をバッファか配列に読み込むコードを書きたいです。

  • 解決済

    NullPointerExceptionの原因がわからない

    filereaderで読んだ文字を二次元配列に格納したいのですがぬるぽが出ます public String[][] read(String path) { String[][]

  • 解決済

    javaの演算子に関する質問です。

    キーボードから読み込んだ整数値に10を加えた値と,10減らした数を表示するプログラムを作っています。一応プログラムは完成したのですがコンパイルエラーになります。なぜでしょうか??プ

  • 解決済

    Javaでarraylistを使って任意順のソートをしたい

    前提・実現したいこと CSVを読んで中身を変換、ソートして標準出力をしたい。 CSVの中身は 1 A100,yyyyMMdd,名前 S234,yyyyMMdd,名前

  • 解決済

    Javaもしくは、openoffice calcを用いて様々な文字列を数値に変換したい

    Javaについての質問です。 このようなテキストファイルがあるとします userID           venueID     star g;ajgfadjfajk

  • 解決済

    javaの配列に文字を格納して処理する方法

     疑問、質問 javaについての質問です。 キーボードから文字を一字ずつ入力し配列に格納する。 その後配列に格納されていた文字によってそれぞれ順番に処理していくというプログラ

同じタグがついた質問を見る

  • Java

    14142questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • CSV

    677questions

    CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。