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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CSV

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

Java

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

Q&A

解決済

5回答

4486閲覧

集計したデータの並べ替えを実現するには?

lena

総合スコア31

CSV

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

Java

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

0グッド

0クリップ

投稿2016/03/30 02:06

JAVA初心者です。
月別の売上金額の大きい3商品を出力するプログラムを
作成しています。
以前こちらで問題点を解決いただき、完成には近づいているのですが
再び自身では解決できないことがあり投稿させていただきました。

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

【仕様内容】
売上明細をもとに商品マスタより商品名と単価を取得します。
売上金額の大きい商品の順に並び替えをして上位3つを出力します
(sort機能は使用しない)。
商品を出力する前に「yyyymm月売上高BEST3」を出力します。

【解決したいこと】
売上データが蓄積されたHashMapから合計金額を抽出し新たな配列に格納して大きい順に
並び替えをしたいのですが、sortAmountメソッドのところで「演算子 < は引数の型
lesson.Profit, lesson.Profit で未定義です」とEclipseに指摘されてしまいます。
この場合はどうすればよろしいのでしょうか?

どうぞよろしくお願いいたします。

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; import java.util.Map.Entry; public class MonthlySalesBest3 { public static BufferedWriter bwA = null ; //月額売上表出力ファイル public static void main(String[] args) { BufferedReader brA = null ; //売上明細入力ファイル String stA = ""; //inAファイルデータを格納 String[] itemA = null ; //inAファイルデータを配列に格納 HashMap<String, Profit> totalHolder = null ; //商品別一式の売上データを格納 String date = ""; //売上明細ファイルの購入月をセット boolean isFirst = false; //0番目の購入日をセットする為の変数 final String noItem = "商品マスタ未存在"; final String noDate = "日付に誤りがあります"; boolean emptyflgA = false; //売上明細入力ファイル空判定フラグ try{ fileError:{ 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ファイルが見つかりません。"); } /** * 商品マスタ一覧を入力するメソッド */ ProductMasterList.productList(); bwA.write("商品名" + "," + "数量" + " ," + "売上金額" + " ," + "備考"); //ヘッダー行を出力 bwA.newLine(); try{ while((stA = brA.readLine()) != null){ if(stA.equals("")){ System.err.println("データに不備があります。"); break fileError; } emptyflgA = true; itemA = stA.split(","); ProductMasterList.mpDM = ProductMasterList.alDM.get(itemA[1]); if(isFirst == false){ //date変数に売上月がセットされているか確認 date = itemA[0].substring(0, 6); isFirst = true; } String soldDate = (itemA[0].substring(0, 6)); int sold= soldDate.compareTo(date); //月変更の比較 if(sold > 0){ bwA.write(date.substring(0, 6) + "月売上高BEST3"); //月売上高BEST3を出力 bwA.newLine(); Profit[] arr = null; int i = 0; for(Entry<String, Profit> entry : totalHolder.entrySet()) { //System.out.println(entry.getKey() + " ," + entry.getValue().count + " ," + entry.getValue().salesAmount); arr = totalHolder.values().toArray(new Profit[i]); //System.out.println(arr[i]); i += 1; } /** * 売上金額を大きい順に並べ替えるメソッド */ sortAmount(arr); date = itemA[0]; //売上日を再セット } if(ProductMasterList.alDM.containsKey(itemA[1])){ if(checkDate(itemA[0])){ //日付の妥当性を確認 if(totalHolder == null){ totalHolder = new HashMap<String, Profit>(); } String itemName = (String) ProductMasterList.mpDM.get("name"); if(!totalHolder.containsKey(itemName)) { //totalHolderに名前が登録されてなければ新しく登録。 totalHolder.put(itemName, new Profit()); totalHolder.get(itemName).itemName = itemName; // あとで値出力の時に使う } // 売上数量と売上金額を加算。 totalHolder.get(itemName).count += Integer.parseInt(itemA[2]); totalHolder.get(itemName).salesAmount += Integer.parseInt(itemA[2]) * Integer.parseInt(ProductMasterList.itemM[2]); } else{ String e = ""; //備考 e = noDate; //備考=日付に誤りがあります } }else{ Object b = noItem; //商品名=商品マスタ未存在 } }//while if(emptyflgA == false){ System.err.println("inA.csvファイルが空です。"); break fileError; } }catch(IOException e){ e.printStackTrace(); } }//fileError }catch(IOException e){ System.err.println("何らかのエラーが発生しました。"); } finally{ try { brA.close(); ProductMasterList.brM.close(); bwA.close(); } catch (IOException e) { e.printStackTrace(); } } }//main /** * 日付の妥当性をチェック * カレンダーに存在するかどうかを返す。 * 存在する日付の場合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; } } /** * 売上金額を大きい順に並べ替えるメソッド */ public static Profit[] sortAmount(Profit[] arr){ for(int i=0; i<arr.length-1; i++){ //売上金額を昇順に並べ替え for(int j=i+1; j < arr.length; j++){ if(arr[i] < arr[j]){ Profit temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; } } } return arr; } /** * 売上金額の上位3位を出力するメソッド */ public static void outputBest3(){ for(int i=0; i < 3; i++){ String name = totalHolder.get(itemName).itemName[i]; //商品名 int cnt = totalHolder.get(itemName).count[i]; //数量 int amt = totalHolder.get(itemName).salesAmount[i]; //合計額 bwA.write(name + "," + cnt + "," + amt + ","); bwA.newLine(); } } }
package lesson; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.HashMap; public class ProductMasterList { public static BufferedReader brM = null ; //商品マスタ入力ファイル public static String stM = ""; //inMファイルデータを格納 public static String[] itemM = null ; //inMファイルデータを配列に格納 public static HashMap<String, Object> mpDM = null; //商品マスタデータを格納 public static HashMap<String,HashMap<String,Object>> alDM = new HashMap<String,HashMap<String,Object>>() ; //商品マスタの入力データを格納 public static boolean emptyflgM = false; //商品マスタファイル空判定フラグ public static HashMap<String, HashMap<String, Object>> productList( ){ try{ try { brM = new BufferedReader(new InputStreamReader(new FileInputStream("C:/Users/temp/Desktop/inM.csv"),"JISAutoDetect")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }catch(FileNotFoundException e){ System.err.println("inM.csvファイルが見つかりません。"); } //inMファイルデータを読み込み try { while((stM = brM.readLine()) != null){ if(stM.equals("")){ System.err.println("データに不備があります。"); } 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); //商品コードをキー、mpDMを値にして格納 } } catch (IOException e) { e.printStackTrace(); }//while if(emptyflgM == false){ System.err.println("inMファイルが空です。"); //break fileError; } return alDM; } }
package lesson; class Profit { /** 商品名 */ public String itemName = null; /** 売上数量 */ public int count = 0; /** 売上金額 */ public int salesAmount = 0; }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

前の方の回答の通り、数値の比較に使う<>をオブジェクトに使うことは出来ません(数値のラッパークラスオブジェクトを除く)。
簡単に並べ替えを実現するには、Comparator<Profit>実装クラスを作ってArrays.sortに配列ともども渡すことですね。

投稿2016/03/30 02:35

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lena

2016/03/31 03:28

swordonerさん、他の並べ替えの方法も教えていただきありがとうございました。 数値の比較に使う<>をオブジェクトに使うことは出来ないとのことですが、数値のラッパークラスオブジェクトなら<>が使えるのですか? よろしければ使い方の例などを教えていただけないでしょうか?
swordone

2016/04/01 09:45

ラッパークラスオブジェクトは必要に応じて元の数値型に自動で変換されます。これを「アンボクシング」と呼びます。この機能のため、ラッパークラスオブジェクトは例外的に不等号の比較演算子が使えるのです。
lena

2016/04/01 10:20

swordonerさん、ラッパークラスオブジェクトについて教えていただきありがとうございました。
guest

0

ベストアンサー

class MonthlySalesBest3内、メソッドsortAmountでのif文「if(arr[i] < arr[j]){」←arr[i]はProfitクラスのインスタンスです。
クラスのインスタンスどうしなのでこれでは比較ができません。
class Profitで比較するのに使うのはなんでしたっけ?
売上金額ではないですか?

class Profit { /** 商品名 */ public String itemName = null; /** 売上数量 */ public int count = 0; /** 売上金額 */ public int salesAmount = 0; // <- これで比較するんじゃね? }

ではsalesAmountを取ってくるにはどうすればいいでしょう?
インスタンスのpublicなメンバ変数にアクセスするには「[インスタンス名].[メンバ変数名]」です。
arr[i]のsalesAmountにアクセスするなら「arr[i].salesAmount」としなければ。
これをほかの売上金額と比較するんでしょ?
「if ( 1 < 2 )」の1、2に該当するところに「arr[i].salesAmount」などなどを入れるのです。

ついでに、

/** * 売上金額の上位3位を出力するメソッド */ public static void outputBest3(){ for(int i=0; i < 3; i++){ String name = totalHolder.get(itemName).itemName[i]; //商品名 int cnt = totalHolder.get(itemName).count[i]; //数量 int amt = totalHolder.get(itemName).salesAmount[i]; //合計額 bwA.write(name + "," + cnt + "," + amt + ","); bwA.newLine(); } }

↑これは何をしているのでしょう?
「totalHolder」はstatic なHashMap<String, Profit>なはずです。

totalHolder.get(itemName).salesAmount[i]; //合計額

↑こんなんしてもコンパイルエラーになりますよ?

■以下追加:

for(Entry<String, Profit> entry : totalHolder.entrySet()) { //System.out.println(entry.getKey() + " ," + entry.getValue().count + " ," + entry.getValue().salesAmount); arr = totalHolder.values().toArray(new Profit[i]); //System.out.println(arr[i]); i += 1; }

まずここ。
無意味なループです。
ここでやりたいことは

・「Profit[] arr = null;」で宣言したProfitインスタンスの配列にHashMap<String, Profit>の中身を詰め込む。

ことですね。

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

この1行で完了します。

また、

/** * 売上金額を大きい順に並べ替えるメソッド */ sortAmount(arr);

ここではメソッドにProfit配列を渡して処理してもらってますね?

これと同じように、出力するメソッドも

/** * 売上金額の上位3位を出力するメソッド */ public static void outputBest3(Profit[] arr){

のように定義してやって、このメソッドにソートが終わった配列を渡してあげれば完了ではありませんか?

// outputBest3の実行 outputBest3(arr);

まとめ:
こんな書き方になるはずです。

if(sold > 0){ // 1.新しい月の売上が出てきたので、今までの分を出力 // 2.処理対象の月のヘッダを出力する bwA.write(date.substring(0, 6) + "月売上高BEST3"); bwA.newLine(); // 3.Profitインスタンスの配列にHashMap<String, Profit>の中身を詰め込む arr = totalHolder.values().toArray(new Profit[]); // 4.上で取得したProfit配列を売上金額が大きい順に並べ替える sortAmount(arr); // 5.売上金額の上位3位を出力する outputBest3(arr); date = itemA[0]; //売上日を再セット }

**「何を」「どうする」**というのがしっかり切り分けられないとプログラムになりません。(この場合の主語は「プログラムが」)
このことが明確になってないとプログラムはおかしくなります。
たとえば質問のソースで

// 商品マスタ一覧を入力するメソッド ProductMasterList.productList();

こんなのがありましたが、この1行でやってることはなんですか?
**「何を」「どうする」にあてはめると、「商品マスタ一覧を」「取得する」**ではありませんか?
入力じゃないですよね?
ささいなことかもしれませんが、コメントに書いていることと実際の処理内容が食い違っていれば勘違いや混乱のもとになります。

投稿2016/03/30 02:22

編集2016/03/31 04:23
tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lena

2016/03/31 03:12

tkturboさん、いつもご丁寧にご回答いただきありがとうございます。 class Profitの売上金額を比較しないといけないことは分かっていたのですが、 メンバ変数にアクセスする方法が分かりませんでした、教えていただきありがとう ございました。 それから、outputBest3メソッドについて、改めて考えると「totalHolder」はインスタンスではないので、コンパイルエラーになるのは当然だと分かりました。 では、どうすれば並べ替えをしたインスタンスの情報を取り出すことができるのか教えていただけないでしょうか? よろしくお願いいたします。
tkturbo

2016/03/31 04:31 編集

回答を編集しました。「以下追加」以降のところを読んでみてください。
lena

2016/04/01 09:27

tkturboさん、たくさんのご指摘やご教授いただきありがとうございました。 今の私には、ご説明いただいた内容を明確に理解することは難しいですが、 教えていただいたことを整理しながら理解していけるよう努めていきます。 何度もご質問して申し訳ありませんが、 >arr = totalHolder.values().toArray(new Profit[]); 上記の箇所の(new Profit[])に「変数はディメンション式または配列イニシャライザーのどちらかを提供しなければなりません」とエラーが表示されるのですが、どのように対処すれば良いのか、またこのエラー内容はどのような意味なのか教えていただけないでしょうか、よろしくお願いいたします。
tkturbo

2016/04/01 09:29

new Profit[] → new Profit[0] に変更で。
lena

2016/04/01 10:19

tkturboさん、早急なご回答ありがとうございました。 的確なご指摘をいただいたおかげで無事すべての問題点が解決しプログラムが完成しました。 本当にありがとうございました。
guest

0

エラーの原因)
Profitクラスのオブジェクトどうしを、"<"で比較しようとしているのですから、エラーになります。
"<"は、数値比較の演算子ですから。

sortAmountのコードを以下のように修正すれば、問題は解決すると思います(動作確認はしていません)

Java

1 public static Profit[] sortAmount(Profit[] arr){ 2 3 for(int i=0; i<arr.length-1; i++){ //売上金額を昇順に並べ替え 4 for(int j=i+1; j < arr.length; j++){ 5 // if(arr[i] < arr[j]){ //この行でエラーが出ている 6 if(arr[i].salesAmount < arr[j].salesAmount){ //オブジェクトどうしを比較するのではなく、売上金額(salesAmount)どうしを比較するように修正。 7 Profit temp=arr[i]; 8 arr[i]=arr[j]; 9 arr[j]=temp; 10 } 11 } 12 } 13 return arr; 14 }

投稿2016/03/30 02:25

coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lena

2016/03/31 03:21

coco_bauerさん、エラー原因を丁寧にご説明いただきありがとうございました。 ご指摘とおりに修正したらエラーが解消できました。
guest

0

Profitのインスタンスを < で比較しているからでしょう。

arr[i].salesAmount < arr[j].salesAmount ではないですか?

投稿2016/03/30 02:17

root_jp

総合スコア4666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lena

2016/03/31 02:57

root_jpさん、具体的なご回答をありがとうございました。 arr[i].salesAmount < arr[j].salesAmountで並び替えすることが出来ました。
guest

0

自作クラスProfitに対しては比較演算子は使えません。
Profit#salesAmountに対しての比較に変更する必要があります。

投稿2016/03/30 02:13

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lena

2016/03/31 02:55

yonaさん、具体的なご回答をありがとうございました。 自作クラスProfitのフィールドsalesAmountに対して使わないといけないんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問