おふとんガレージ

技術的な忘備録とか雑記

Javaで動的に2次元以上の配列を使いたい

Java微塵もわかんない太郎なのに講義で書かなくてはいけない機会があったのでアレする。

仕様

int MailCharge.calcMailCharge(int type, int weight)

関数名:calcMailCharge
引数: 定形(1)か定形外(2)か(int)、郵便物の重量(g) (int)
返り値:引数の重量に対する郵便料金(int)
関数の内容:
  • 引数として郵便物の内容、重量を受け取り、重量から郵便料金を計算して返す。
  • 郵便物の内容は、1:定形郵便物、2:定形外郵便物とする。
  • 入力される郵便物の重量は単位をgとする。
  • 計算可能な郵便物の個数は1 個とする。
  • 計算可能な種類は以下に示す第一種郵便物に限り、重量は1g以上とし上限は表に従う。
  • 定形郵便の料金は以下の通りとする。
エラー処理:

郵便物の種類として、1および2以外の数値が入力された場合、-1 を返す。
0g以下、および上記表に指定されていない重量が入力された場合、-2 を返す。

めんどくさいので表は省略


問題としては非常に単純だし、思考停止してif文で場合分けすれば一瞬で終わる。
ただ、見ててイライラしてくるコードになるのは間違いない。

Mailcharge.java

package sqc_report1;

import java.util.*;

public class Mailcharge {
	
	public Mailcharge(){}
	
	int calcMailCharge(int type, int weight){
		
		if(weight < 0) return -2;
		if(type == 1){
			if(weight <= 25) return 80;
			else if(weight <= 50) return 90;
			else return -2;
		}else if(type == 2){
			if(weight <= 50) return 120;
			else if(weight <= 100) return 140;
			/*以下省略*/

		}
 	}
}

クソ

なにより要素が増えたり変更があったときがアレすぎてアレ。

なので、配列の中に表を格納し、それぞれの要素を順に比較するようにしてみる。

Mailcharge.java

package sqc_report1;

import java.util.*;

public class Mailcharge {
	
	public Mailcharge(){}
	
	int calcMailCharge(int type, int weight){
		ArrayList<ArrayList<Integer>> postage1 = new ArrayList<>();
		ArrayList<ArrayList<Integer>> postage2 = new ArrayList<>();
		addElement(postage1, 25, 80);
		addElement(postage1, 50, 90);
		
		addElement(postage2, 50, 120);
		addElement(postage2, 100, 140);
		addElement(postage2, 150, 200);
		addElement(postage2, 250, 240);
		addElement(postage2, 500, 390);
		addElement(postage2, 1000, 580);
		addElement(postage2, 2000, 850);
		addElement(postage2, 4000, 1150);
		
		switch(type){
		case 1:
			return comparison(postage1, weight);
		case 2:
			return comparison(postage2, weight);
		default :
			return -1;
		}				
	}
	
	void addElement(ArrayList<ArrayList<Integer>> postage, int weight, int price){
		ArrayList<Integer> sub = new ArrayList<>();
		sub.add(weight);
		sub.add(price);
		postage.add(sub);
	}
	
	int comparison(ArrayList<ArrayList<Integer>> postage, int weight){
		if(weight < 1) return -2;
		
		for(int i = 0; i < postage.size(); i++){
			if(weight <= postage.get(i).get(0)) return postage.get(i).get(1);
		}
		return -2;
	}
}

あんまり綺麗じゃないが、前のやつよかマシな気がする。

ArrayList<型>

動的配列を使用できる。.add(element)で要素追加、.get(element)で要素を取り出す。.clear()で中身を吹き飛ばす。

ArrayList<型> hoge = new ArrayList<>();

で初期化、入れ子も可能。

今回はpostage1, postage2の2つを宣言した。
これらをまとめた方がエレガントな気もするが、3重の入れ子使うならクラス宣言した方がいいだろうし、この程度の内容でクラス分けちゃうと個人的に可読性が落ちる気がしたのでまぁ。
なによりもオブジェクト指向がわかってないのがよくない(戒め)

今回は2重の入れ子で使用、いちいち毎回一時的にArrayListに突っ込んでそれを別のArrayListに突っ込み、一時的に使った方を消して再度~みたいな処理の繰り返しなのでメソッドとして定義している。

2重にした場合もgetの重ねがけで要素を持ってこれる。HashMap使ってforeachで回した方がいいかも。

結論

オブジェクト指向わかんないめう

追記

復習のために久々にコード見たらほんとにクソコードで猛烈に腹が立ったので書き直した。
毎回判定の度に判定用配列作り直してるのチンパンジーでもやらないと思う。

package sqc_report1;

import java.util.ArrayList;
import java.util.List;

public class Mailcharge {
	List<List<Integer>> postage1;
	List<List<Integer>> postage2;

	public static void main(String[] args) {
		// TODO 自動生成されたメソッド・スタブ
		Mailcharge mailcharge = new Mailcharge();
		// 定型,40g
		System.out.println(mailcharge.calcMailCharge(1, 40));
		// 定型外, 400g
		System.out.println(mailcharge.calcMailCharge(2, 40));
	}

	public Mailcharge(){
		postage1 = new ArrayList<>();
		postage2 = new ArrayList<>();
		addElement(postage1, 25, 80);
		addElement(postage1, 50, 90);

		addElement(postage2, 50, 120);
		addElement(postage2, 100, 140);
		addElement(postage2, 150, 200);
		addElement(postage2, 250, 240);
		addElement(postage2, 500, 390);
		addElement(postage2, 1000, 580);
		addElement(postage2, 2000, 850);
		addElement(postage2, 4000, 1150);
	}

	void addElement(List<List<Integer>> postage12, int weight, int price){
		ArrayList<Integer> sub = new ArrayList<>();
		sub.add(weight);
		sub.add(price);
		postage12.add(sub);
	}

	int calcMailCharge(int type, int weight){
		switch(type){
		case 1:
			return comparison(postage1, weight);
		case 2:
			return comparison(postage2, weight);
		default :
			return -1;
		}
	}


	int comparison(List<List<Integer>> postage, int weight){
		if (weight < 1) return -2;

		for (List<Integer> item : postage) {
			if(weight <= item.get(0)) return item.get(1);
		}
		return -2;
	}

}

もっとキレイに書ける気がする。なんもわからん。