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

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

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

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

Struts

StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

4回答

12556閲覧

二つのListを比較して違いがあれば行単位で抽出したい

pingu612

総合スコア13

Java

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

Struts

StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2017/01/25 08:11

編集2017/01/26 06:25

###前提・実現したいこと
マスタとなるExcelを読み取って生成した二つのListを1行ずつ比較して、要素に違いがあれば行単位で抽出したいです。
上期マスタ:empPostList
下期マスタ:empLastPostList です。

抽出パターンは以下の通りです。
①上期マスタにあって下期マスタにない行(追加分)
②下期マスタにあって上期マスタにない行(削除分)
③変更のない行

###発生している問題・エラーメッセージ
思いつく方法で比較をしてみましたが、
全行変更なしとして抽出されてしまいます。

※1/26追記
Excelから生成したListに問題があったようで、現在試すと
仰る通りほとんど「削除」に入っていく状態です。
「削除」部分のelse ifを削ると「変更なし」と「変更あり」については期待通りの動作をしています。
「削除」(下期マスタにあって上期マスタにない行)の抽出方法を模索しているところです。
elseで対応してみたりしましたが、どうにもうまくいかない状況です。。

###該当のソースコード

Java

1 //「変更なし」格納用List 2 ArrayList<EmpPostBean> noChange = new ArrayList<EmpPostBean>(); 3 // 「変更あり」格納用List 4 ArrayList<EmpPostBean> Change = new ArrayList<EmpPostBean>(); 5 // 「削除用」格納用List 6 ArrayList<EmpPostBean> Del = new ArrayList<EmpPostBean>(); 7 8 9 10 // 上期マスタ 11 for (EmpPostBean This : empPostList) { 12 // 下期マスタ 13 for (EmpPostBean Last : empLastPostList) { 14 // 年、期、従業員ID、役職コードがすべて一致する場合 15 if (This.getYear().equals(Last.getYear())&&This.getTerm().equals(Last.getTerm())&&This.getDscId().equals(Last.getDscId())&&This.getPostCode().equals(Last.getPostCode())) { 16 noChange.add(This); 17 System.out.println("変更なしの行数:" + noChange.size()); 18 19 break; 20 21 // 従業員IDが一致し、役職コードが不一致の場合 22 }else if(This.getDscId().equals(Last.getDscId())&& !This.getPostCode().equals(Last.getPostCode())){ 23 Change.add(This); 24 System.out.println("変更ありの行数:" + Change.size()); 25 26 break; 27 28 // 従業員IDが一致しないが、役職コードがNULLでない場合 29 }else if(!This.getDscId().equals(Last.getDscId())&& This.getPostCode().isEmpty()|| Last.getPostCode().isEmpty()){ 30 Del.add(This); 31 System.out.println("削除の行数:" + Change.size()); 32 33 break; 34 } 35 } 36 } 37

※1/26追記
HashMapを使う方法を試行してみました。
今度は削除分はうまく動作しましたが、「変更なし」分が取れていないみたいです。
キーが一致したifに入った場合、更にif文でValue値のチェックを行っており、そこでcontainsValueがtrueになればキーもValue値も一致することになるので、「変更なし」に追加すると記述したつもりです。
ご指摘あればよろしくお願いします。

Java

1 // 今期マスタをHashMapに詰める 2 Map<String, EmpPostBean> Thismap = new HashMap<String, EmpPostBean>(); 3 for (EmpPostBean This : empPostList) { 4 5 // キーと値をセット 6 Thismap.put(This.getDscId(),This); 7 } 8 9 // 前期従業員マスタの要素がHashMapに含まれていれば変更なしリストに追加する 10 for (EmpPostBean This : empLastPostList) { 11 12 // キーが一致 13 if(Thismap.containsKey(This.getDscId())) { 14 // 役職コードが一致 15 if(Thismap.containsValue(This.getPostCode())){ 16 //変更なしリストに追加 17 noChange.add(This); 18 System.out.println("変更なしの行数:" + noChange.size()); 19 20 // 役職コードが不一致 21 }else{ 22 // 変更ありリストに追加 23 Change.add(This); 24 System.out.println("変更ありの行数:" + Change.size()); 25 } 26 }else{ 27 28 Del.add(This); 29 System.out.println("削除の行数:" + Del.size()); 30 } 31 }

###試したこと
・比較を行う際、equalsでなく「==」で試してみる
・HashMapを使って比較してみる
→キー指定が分からず断念しています。

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

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

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

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

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

swordone

2017/01/26 01:37

全行「変更なし」なのですか?これ冷静に考えるとほとんどが「削除」に入りそうなのですが…
guest

回答4

0

ちょっと要件が不明なところがありますが、2つのListの要素が一致しているものだけを抽出した新しいListを作成するのであれば、EmpPostBeanでequalsとhashCodeメソッドを適切に実装したうえで、以下のコードだけで済みませんか?

java

1ArrayList<EmpPostBean> noChange = empPostList.stream() 2 .filter(o -> empLastPostList.contains(o)) 3 .collect(Collectors.toList());

dscIdが同じでpostCodeが異なるものだけを抽出するのであれば以下のようになります。

java

1ArrayList<EmpPostBean> Change = empPostList.stream() 2 .filter(o -> empLastPostList.stream() 3 .anyMatch(o2 -> o.getDscId().equals(o2.getDscId()) && 4 !o.getPostCode().equals(o2.getPostCode()))) 5 .collect(Collectors.toList());

3つ目の要件ですが、書かれているコードの条件式おかしくないですか?
ちなみにisEmptyはnull判定用のメソッドではありません。

投稿2017/01/25 12:57

amadablam

総合スコア402

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

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

pingu612

2017/01/26 01:16

ご回答ありがとうございます。 streamメソッドの実装を試みましたが、JDKのバージョンが古いため実装出来ませんでした。 都合によりJDKのバージョンを変更できないため、別の方法を模索するしかないようです。 null判定についてご指摘ありがとうございます、仰る通りでした。。
guest

0

ベストアンサー

1行ごとに各if条件をチェックするので、1行目でIDが一致しなければ、仮にほかの行で一致するものがあったとしても「削除」と判定されてしまいます。
なのでこの方法でやるとしたら、内側のforを抜けた後で削除リストへの追加を行うべきです。
「empPostListからの要素で、empLastPostListにIDが同じものがなかった」という状態ですから。

HashMapのキー値が思いつかなかったということですが、変更・追加・削除の基準が従業員IDなので、それをキーにしてしまえばいいのです。

投稿2017/01/26 02:02

swordone

総合スコア20649

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

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

pingu612

2017/01/26 02:26

ご回答ありがとうございます。 内側forを抜けた後に削除リストへの追加を試してみたいと思います。 HashMapの方は従業員IDをキーにして、残りを値とするところまでは理解できました。 キーが一致していて、値が一致→変更なしリストに追加 キーが一致していて、値が一部違った場合(具体的には役職コード)→変更ありリストに追加 キーが一致しない→削除リストに追加 ということでしょうか?
swordone

2017/01/26 02:50

そうですね。ただし「追加分(前なかったが今ある)」の処理ができないので、逆パターンで処理するか、全体をデザインしなおすかですね。
swordone

2017/01/26 03:20

あ、フラグを用意しておかないと必ず削除に入っちゃうことに今気づいた
pingu612

2017/01/26 07:49

ご回答ありがとうございます。 追加分については逆パターンで処理をしてみようと思います。 HashMapを使った処理に書き直してみましたが、削除分はContainKeyのElseで処理を行っています。 追加分をContainValueで処理したところ、ifに入らずうまく比較が出来ていないようです。 コードを記載してみたので、ご指摘いただけますでしょうか?
swordone

2017/01/26 14:58

格納している値はEmpPostBean型なのですから、その中のgetPostCode()でえられる値がマップの値として入っているわけがありません。マップに対してキーを使ってget()し、それに対してgetPostCode()を実行しないと検証できません。
pingu612

2017/01/27 07:20

ありがとうございます。 Mapの生成方法とif文の判定条件を見直した後、期待通りに挙動しました!
guest

0

プログラムにこだわるのでなければ、diff でもとれば済みそうな……
それはさておき、概念的にはこんなところでしょうか。

Java

1int firstIdx = 0; 2int secondIdx = 0; 3while(true) { 4 // ループ脱出チェック 5 if (firstIdxがempPostListの件数以上になるか、secondIdxがempLastPostListの件数以上になる) { 6 break; 7 } 8 // 双方を取り出す 9 empPostBean firstBean = empPostList[firstIdx]; 10 empPostBean secondBean = empLastPostList[secondIdx]; 11 // 比較 12 if (firstBeanとsecondBeanが一致) { 13 // TODO: 一致のリストに入れる 14 firstIdx++; 15 secondIdx++; 16 } else if (firstBeanの方がsecondBeanより小さい = 前期にあり後期にない) { 17 // TODO: 前期のみのリストに入れる 18 firstIdx++; 19 } else if (firstBeanの方がsecondBeanより大きい = 後期にあり前期にない) { 20 // TODO: 後期のみのリストに入れる 21 secondIdx++; 22 } 23} 24// TODO: 前期側リストの末尾まで行っていなければ、残りをすべて前期のみのリストに入れる 25// TODO: 後期側リストの末尾まで行っていなければ、残りをすべて後期のみのリストに入れる

リストのそれぞれの着目位置を独立して制御するわけです。Excel で二つのシートを並べ、上から1行ずつ比較していくイメージですね。

投稿2017/01/26 01:42

tacsheaven

総合スコア13703

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

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

pingu612

2017/01/26 02:22

ご回答ありがとうございます。 リストのインデックス位置を見て判断しているということでしょうか? そういう考え方は盲点でした。ちょっと試行してみます。 ありがとうございます!
guest

0

方向性は合ってるのでif文の条件判定がきちんと動作してないのではないでしょうか。
一個一個ブレークポイント張ってデバッグでとめて変数の中身を確認しながらきちんと条件を通るか確認してみれば自力でいけませんか。

投稿2017/01/27 01:53

tantanegg

総合スコア213

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

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

pingu612

2017/01/27 07:21

ご回答ありがとうございます。 仰る通り、条件判定の部分がきちんと動いていませんでした。 containsValueで判定していたことが原因で、Mapのキーを使ってValueを取得したところ、正しく判定ができました。 ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問