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

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

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

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

Q&A

解決済

6回答

3581閲覧

javaで効率のよい書き方

settyan

総合スコア60

Java

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

0グッド

0クリップ

投稿2016/07/21 06:06

編集2016/07/21 06:30

いつもお世話になっております。

今回は効率化(?)について質問させていただきます。

###やりたいこと
String型の配列に入っている”2016/07/20”という文字列を使って2つのmapを作りたいんです。

例)

java

1String[] list = 2{ 3"2014/12/01", 4"2015/01/01", 5//~~~~~中略~~~~~~ 6"2016/05/01", 7} 8 9//上記のものを 10 11 12//下記の形に動的に書き換えたいのですが... 13private Map<Integer,String> years; 14private Map<String,List<String>> yearMonths; 15 16years.put("0", "2014"); 17years.put("1", "2015"); 18years.put("2", "2016"); 19 20yearMonths.put("2015", Arrays.asList("12")); 21yearMonths.put("2016", Arrays.asList("1","2",/*中略*/"11","12")); 22yearMonths.put("2017", Arrays.asList("1","2","3","4","5"));

自分で作ってみたはいいもののコレは実用化できるものなのか?と思い質問させていただきました。
ちなみに今はyearMonthsの中身が連続していますが後々虫食いになる可能性があるので動的に生成させています。

下記が自作で作ったものです。
※mDが上記のlistの代わりのものです。

java

1 2//private Map<Integer,String> years; ...① 3//private Map<String,List<String>> yearMonths; ...② 4 5//②のList<String>の部分に入れ込む配列を生成 6ArrayList<String> monthlist = new ArrayList<String>(); // ...③ 7 8 for (int i = 0; i < mD.size(); i++){ 9 10 if(i == 0){ /**初回*/ 11 12 //最小年の①を作成 13 years.put(i,mD.get(i).getMonth().substring(0, 4)); 14 15 //③に月を追加 16 monthlist.add(mD.get(i).getMonth().substring(5, 7)); 17 18 }else{ /**二回目以降*/ 19 20 21 //1つ前の配列と現在の配列で年の部分が同値でないかの判定 22 if(mD.get(i).getMonth().substring(0, 4).equals(years.get(years.size()-1)) ) 23 { 24 /**同値の場合*/ 25 26 //③に月を追加 27 monthlist.add(mD.get(i).getMonth().substring(5, 7)); 28 29 }else{ 30 31 /**同値でない場合*/ 32 33 //今まで月を追加してきた③のリストを使い②を作成する 34 yearMonths.put(mD.get(i - 1).getMonth().substring(0, 4), monthlist); 35 //挿入した③のリストはいらないので初期化 36 monthlist = new ArrayList<String>(); 37 38 //次年度の①を作成する 39 years.put(years.size(),mD.get(i).getMonth().substring(0, 4)); 40 41 //③に月を追加 42 monthlist.add(mD.get(i).getMonth().substring(5, 7)); 43 } 44 45 if(i == mD.size()-1){ 46 //最後に今まで月を追加してきた③のリストを使い②を作成する 47 yearMonths.put(mD.get(i - 1).getMonth().substring(0, 4), monthlist); 48 //挿入した③のリストはいらないので初期化 49 monthlist = new ArrayList<String>(); 50 } 51 } 52 } 53

いかがでしょうか。

ご教授願います。

###追記
効率について追記させていただきます。

なるべく負荷のかからない形
もしくは
実行時間が短い形
の2点を想定しています。

javaのバージョンは8です。

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

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

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

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

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

coco_bauer

2016/07/21 06:13

「効率」の定義は? コードが短い(文字数が少ない)、実行時間が短い(実行が早い)など、視点が異なる様々な効率がありうるかと思うのですが。
settyan

2016/07/21 06:20

そうですよね... 何の効率を書かずになんて... 効率について追記させていただきました。 ご指摘ありがとうございました。
yuba

2016/07/21 06:21

Javaのバージョンは8ですか?
settyan

2016/07/21 06:30 編集

ご指摘ありがとうございます。 java8です。
guest

回答6

0

ストリームの部分を、他の言語でのタプルを使うイメージで書いてみました。
ただ、SimpleEntryを使うのはたぶんあまり一般的じゃないですね。

yearsの方は、ストリームにするとかなり見苦しくなりそうなので単純なループにしました。

効率が良いかどうかはなんとも言えません。

lang

1// import java.util.*; 2// import java.util.AbstractMap.SimpleEntry; 3// import java.util.stream.*; 4 5String[] list = { "2014/12/01", "2015/01/01", "2015/02/01", "2015/03/01", "2015/04/01", "2015/05/01", 6 "2015/06/01", "2016/05/01", }; 7 8Map<Integer, String> years = new HashMap<>(); 9Map<String, List<String>> yearMonths = Stream.of(list).map(x -> { 10 String[] a = x.split("/"); 11 return new SimpleEntry<String, String>(a[0], a[1]); 12}).collect(Collectors.groupingBy(SimpleEntry::getKey, 13 Collectors.mapping(SimpleEntry::getValue, 14 Collectors.toList()))); 15 16List<String> yearList = new ArrayList<>(yearMonths.keySet()); 17Collections.sort(yearList); 18for (int i = 0, n = yearList.size(); i < n; i++) { 19 years.put(i, yearList.get(i)); 20} 21 22System.out.println(years); 23// => {0=2014, 1=2015, 2=2016} 24System.out.println(yearMonths); 25// => {2016=[05], 2015=[01, 02, 03, 04, 05, 06], 2014=[12]}

投稿2016/07/21 08:07

argius

総合スコア9388

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

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

settyan

2016/07/22 00:10

ご解答ありがとうございました! 試行錯誤してみます!
guest

0

自己解決

皆様ご解答ありがとうございました。
様々な書き方を頂いたのですべて試してみようと思います。
僕自身これが言いとまだ決まったわけではないので

ベストアンサーを決めず、自己解決にさせていただきます。
ありがとうございました。

投稿2016/07/22 00:07

settyan

総合スコア60

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

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

0

年の順番付きのリストをなぜMapでやる必要があるのかわからなかったため、LinkedHashMapに一任しました。一応年のListへの変換もしておきました。
Mapへの追加は、computeIfAbsentを使えばキーが入ってるかなどの判定がいらずに1行で済みます。

java

1import java.util.ArrayList; 2import java.util.LinkedHashMap; 3import java.util.List; 4import java.util.Map; 5 6public class Q41805 { 7 8 public static void main(String[] args) { 9 List<String> years = new ArrayList<>(); 10 Map<String, List<String>> yearMonths = new LinkedHashMap<>(); 11 String[] list = { 12 "2014/12/01", 13 // 中略(連続した年月) 14 "2016/05/01", 15 }; 16 for (String date : list) { 17 String[] line = date.split("/"); 18 yearMonths.computeIfAbsent(line[0], k -> new ArrayList<>()).add(line[1]); 19 } 20 years.addAll(yearMonths.keySet()); 21 System.out.println(yearMonths); 22 System.out.println(years); 23 } 24 25}

実行結果

{2014=[12], 2015=[01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12], 2016=[01, 01, 02, 03, 04, 05]}
[2014, 2015, 2016]

投稿2016/07/21 15:49

swordone

総合スコア20651

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

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

settyan

2016/07/22 00:09

LinkedHashMapなるものがあるんですね... ご解答ありがとうございました! 試行錯誤してみます!
guest

0

手元にJava8の環境がないため、Java7で動作確認してあります。

java

1import java.util.Arrays; 2import java.util.HashMap; 3import java.util.List; 4import java.util.Map; 5import java.util.SortedSet; 6import java.util.TreeSet; 7 8public class Hoge { 9 10 private String[] list = { 11 "2014/12/01", 12 "2015/01/01", 13 "2014/01/20", 14 "2016/01/01", 15 "2016/02/01", 16 "2016/03/01", 17 "2016/04/01", 18 "2016/05/01", 19 "2016/06/01", 20 "2016/07/01", 21 "2016/08/01", 22 "2016/09/01", 23 "2016/10/01", 24 "2016/11/01", 25 "2016/12/01", 26 "2016/12/02", 27 }; 28 29 private Map<Integer, String> years = new HashMap<>(); 30 private Map<String, List<String>> yearMonths = new HashMap<>(); 31 32 public void doSomething() { 33 34 SortedSet<String> tmpYears = new TreeSet<>(); 35 Map<String, SortedSet<String>> tmpYearMonths = new HashMap<>(); 36 37 for (String line : list) { 38 String[] splitted = line.split("\\/"); 39 40 tmpYears.add(splitted[0]); 41 42 if (tmpYearMonths.containsKey(splitted[0])) { 43 SortedSet<String> months = tmpYearMonths.get(splitted[0]); 44 months.add(splitted[1]); 45 } else { 46 SortedSet<String> months = new TreeSet<>(); 47 months.add(splitted[1]); 48 tmpYearMonths.put(splitted[0], months); 49 } 50 } 51 52 int i = 0; 53 for (String line : tmpYears) { 54 years.put(i++, line); 55 } 56 57 for (Map.Entry<String, SortedSet<String>> entry : tmpYearMonths.entrySet()) { 58 yearMonths.put(entry.getKey(), Arrays.asList(entry.getValue().toArray(new String[] {}))); 59 } 60 61 System.out.println(years); 62 System.out.println(yearMonths); 63 } 64}

実行結果

{0=2014, 1=2015, 2=2016} {2014=[01, 12], 2015=[01], 2016=[01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12]}

投稿2016/07/21 07:30

KiyoshiMotoki

総合スコア4791

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

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

settyan

2016/07/22 00:10

ご解答ありがとうございました! 試行錯誤してみます!
guest

0

java

1 final Map<String, List<String>> yearMonths = Stream.of(list) 2 .map(row -> row.split("/")) 3 .collect(Collectors.groupingBy(row -> row[0])) 4 .entrySet() 5 .stream() 6 .collect(Collectors.toMap( 7 g -> g.getKey(), 8 g -> g.getValue().stream() 9 .map(row -> row[1]) 10 .collect(Collectors.toList())));

Java8だとこういう書き方をするんですが、うーん、これはこれでわかりにくいやつですね⋯


追記。Java7以前の機能だけを使った書き方だとこうなります。

java

1 Map<String, List<String>> yearMonths = new HashMap<>(); 2 for (String line: list) { 3 String[] date = line.split("/"); 4 String year = date[0], month = date[1]; 5 List<String> monthList = yearMonths.get(year); 6 if (monthList == null) { 7 monthList = new ArrayList<>(); 8 yearMonths.put(year, monthList); 9 } 10 monthList.add(month); 11 }

投稿2016/07/21 07:14

編集2016/07/21 13:51
yuba

総合スコア5568

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

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

settyan

2016/07/22 00:11

java8だとそんな書き方があるんですね... ご解答ありがとうございました! 試行錯誤してみます!
guest

0

Java

1Map<String,List<String>> yearMonths =new Map<>(); 2for(String date : mD){ 3 String[] dateArray = date.split("¥/"); 4 if(!yearMonths.contains(dateArray[0]){ 5 yearMonths.put(dateArray[0],new ArrayList<String>()); 6} 7yearMonths.get(dateArray[0]).add(dateArray[1]); 8}

あとはyearMonthsのkeyを並び替えるとyearsが取得できます。

動作確認して無いですけど、多分こんな感じかな。速さとかはわからないですが。

投稿2016/07/21 06:20

yona

総合スコア18155

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

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

settyan

2016/07/22 00:11

ご解答ありがとうございました! 試行錯誤してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問