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

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

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

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

Q&A

解決済

6回答

3538閲覧

【Java】リストからある条件のものを削除

taro_11111

総合スコア4

Java

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

0グッド

0クリップ

投稿2021/08/30 13:48

以下の自作クラスがあります。

Java

1public class Model { 2 3 /** 時刻. */ 4 private LocalTime localTime; 5 /** 身長 */ 6 private int height; 7 /** 体重. */ 8 private int weight; 9 10 public Model(LocalTime localTime, int height, int weight) { 11 this.localTime = localTime; 12 this.height = height; 13 this.weight = weight; 14 } 15}

これをメインクラスでインスタンスを作成し、リストに入れて
時刻が重複しているものをある条件で削除したいのですがうまくできません。
ある条件は身長が低いほうを削除、身長が同じであれば体重が低いほうを削除。
身長も同じであれば、ランダムで1つ残す。
試しに以下のような感じで削除したのですが、リストの中身のオブジェクトが1つも残りませんでした。
どなたか教えて頂ける幸いです。

Java

1 List<Model> list = new ArrayList<>(); 2 3 Model a = new Model(LocalTime.of(0, 0), 60, 90); 4 Model b = new Model(LocalTime.of(0, 0), 60, 90); 5 Model c = new Model(LocalTime.of(12, 0), 65, 90); 6 Model d = new Model(LocalTime.of(12, 0), 70, 80); 7 Model e = new Model(LocalTime.of(15, 0), 80, 90); 8 Model f = new Model(LocalTime.of(15, 0), 80, 90); 9 10 list.add(a); 11 list.add(b); 12 list.add(c); 13 list.add(d); 14 list.add(e); 15 list.add(f); 16 17 for (int i = 0; i < list.size(); i++) { 18 if (list.get(i).getLocalTime() == list.get(i + 1).getLocalTime()) { 19 if (list.get(i).getTall() > list.get(i + 1).getTall()) { 20 list.remove(i + 1); 21 } else { 22 list.remove(i); 23 } 24 } 25 }

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

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

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

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

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

jimbe

2021/08/30 17:55

Model には getLocalTime() 等のメソッドはありませんが。
guest

回答6

0

ベストアンサー

1つの時刻に対して1つのオブジェクトだけ対応付けるという事なので、Mapの出番かなと思います。
「削除する」ではなく、「条件に合うものだけを集めたものを新たに作成する」という事になりますが、扱いやすくなります。
まずModelクラスにComparableを実装しましょう。比較がやりやすくなります。
hope_mucciさんがすでに実装例を示していますが、ここは直感的に従いやすくするために、時刻・身長・体重が大きいものを「大きい」と判定するようにしましょう。そうすると、同じ時刻内では「最も大きい」ものだけ残ればいいことになります。

java

1public class Model implements Comparable { 2 // 中略 3 @Override 4 public int compareTo(Model o) { 5 int comp = this.localTime.compareTo(o.localTime); 6 if (comp != 0) return comp; 7 comp = Integer.compare(this.height, o.height); 8 if (comp != 0) return comp; 9 return Integer.compare(this.weight, o.weight); 10 }

Map作成に移ります。LocalTimeをキーとしたマップにし、被ったら比較して大きいほうを残します。
「ランダムに残す」の部分は、この3要素が同じであれば結局同じものになるので無視します。

java

1 Map<LocalDate, Model> map = new HashMap<>(); 2 for (Model m : list) { 3 map.merge(m.getLocalDate(), m, (v1, v2) -> v1.compareTo(v2) < 0 ? v2 : v1); 4 } 5 List<Model> list2 = new ArrayList<>(map.values());

投稿2021/08/30 16:56

swordone

総合スコア20669

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

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

taro_11111

2021/08/31 14:08

ありがとうございます。 comapareTo()をModel側で実装することによって、期待していた動作となりましたm(__)m
guest

0

課題解決の方針

  • Java 16のrecord型を使ってModelを定義する
  • CollectorsのgroupingByによってLocalTimeが同じModelをグループ分けして、Listを作成する
  • グループ分けされたListをソートまたはリダクションしてModelを1件求める。削除ではなく採用。
  • Optional<Model>が発生しないようにする

Model

record型でかつComparableを実装する。Comparableは降順に並ぶよう定義する

Java

1import java.time.LocalTime; 2 3public record Model(LocalTime localTime, int height, int weight) implements Comparable<Model> { 4 @Override 5 public int compareTo(Model o) { 6 int lt = this.localTime.compareTo(o.localTime); 7 if (lt != 0) return lt; 8 int ht = Integer.compare(this.height, o.height); 9 if (ht != 0) return -ht; 10 return -Integer.compare(this.weight, o.weight); 11 } 12}

グループ分けすると、LocalTimeをキーにList<Model>を値とするマップができあがる。マップの各リストを降順にソートして先頭の1件を取る。

Java

1import java.time.LocalTime; 2import java.util.List; 3import java.util.stream.Collectors; 4 5public class q356940 { 6 7 public static void main(String[] args) { 8 9 var list = List.of( 10 new Model(LocalTime.of(0, 0), 60, 90), 11 new Model(LocalTime.of(0, 0), 60, 90), 12 new Model(LocalTime.of(12, 0), 65, 90), 13 new Model(LocalTime.of(12, 0), 70, 80), 14 new Model(LocalTime.of(15, 0), 80, 90), 15 new Model(LocalTime.of(15, 0), 80, 91), 16 new Model(LocalTime.of(15, 0), 80, 90) 17 ); 18 19 var selected = list.stream() 20 .collect(Collectors.groupingBy(Model::localTime)) 21 .values().stream() 22 .flatMap(l -> l.stream().sorted().limit(1)) 23 .collect(Collectors.toList()); 24 25 selected.forEach(System.out::println); 26 27 } 28 29}

Collectors.minByを使うと簡単ですが、結果がOptional<Model>なので、それを避けるために、初期値を与えるリダクションを記述する必要があります。あるいは、OptionalのorElseを使う後処理を書くか。どちらも簡潔さは損なわれます。

投稿2021/08/31 07:35

xebme

総合スコア1089

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

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

0

既存のリストをあれこれいぢりまわすより、新しいリストをつくったほうがいいとおもいます。ということで、

リストからある条件のものを削除

という要件は満たしていませんが。

  1. 時間ごとに分ける
  2. 身長毎に分ける
  3. 身長の一番でかいのをとる
  4. 体重ごとに分ける
  5. 体重の一番でかいのをとる
  6. ランダムに一件選ぶ

# ま、自分向けにstreamのお勉強がてら書いてみました

java

1import java.time.LocalTime; 2import java.util.*; 3import java.util.stream.Collectors; 4 5public class xxHogege { 6 7 public static void main(final String[] args) throws Exception { 8 final List<Model> list = new ArrayList<>(); 9 10 Model a = new Model(LocalTime.of(0, 0), 60, 90); 11 Model b = new Model(LocalTime.of(0, 0), 60, 90); 12 Model c = new Model(LocalTime.of(12, 0), 65, 90); 13 Model d = new Model(LocalTime.of(12, 0), 70, 80); 14 Model e = new Model(LocalTime.of(15, 0), 80, 90); 15 Model f = new Model(LocalTime.of(15, 0), 80, 90); 16 17 list.add(a); 18 list.add(b); 19 list.add(c); 20 list.add(d); 21 list.add(e); 22 list.add(f); 23 list.add(new Model(LocalTime.of(15, 0), 66, 190)); 24 list.add(new Model(LocalTime.of(15, 0), 55, 290)); 25 26 System.out.println("------"); 27 System.out.println(list); 28 29 final Map<LocalTime, List<Model>> localtimeMap = 30 list.stream().collect(Collectors.groupingBy(x -> x.localTime)); 31 32 // System.out.println("------ localtimeMap"); 33 // System.out.println(localtimeMap); 34 35 final List<Model> newList = localtimeMap.values().stream().map(modelList -> { 36 // System.out.println("------ modelList"); 37 // System.out.println(modelList); 38 39 final TreeMap<Integer, List<Model>> heightMap = 40 new TreeMap(modelList.stream().collect(Collectors.groupingBy(x -> x.height))); 41 final List<Model> maxHeightList = heightMap.get(heightMap.lastKey()); 42 // System.out.println("------ maxHeightList " + heightMap.lastKey()); 43 // System.out.println(maxHeightList); 44 45 final TreeMap<Integer, List<Model>> weightMap = 46 new TreeMap(maxHeightList.stream().collect(Collectors.groupingBy(x -> x.weight))); 47 final List<Model> maxWeightList = weightMap.get(weightMap.lastKey()); 48 // System.out.println("------ maxWeightList " + weightMap.lastKey()); 49 // System.out.println(maxWeightList); 50 51 return maxWeightList.get(new Random().nextInt(maxWeightList.size())); 52 }).sorted(Comparator.comparing(x -> x.localTime)).collect(Collectors.toList()); 53 54 System.out.println("------ newList"); 55 System.out.println(newList); 56 } 57 58 public static class Model { 59 /** 時刻. */ 60 final LocalTime localTime; 61 /** 身長 */ 62 final int height; 63 /** 体重. */ 64 final int weight; 65 66 public Model(LocalTime localTime, int height, int weight) { 67 this.localTime = localTime; 68 this.height = height; 69 this.weight = weight; 70 } 71 72 @Override 73 public String toString() { 74 return Map.of("localTime", localTime, "height", height, "weight", weight).toString(); 75 } 76 77 @Override 78 public boolean equals(Object obj) { 79 return obj != null && this.getClass().equals(obj.getClass()) && this.localTime.equals( 80 ((Model) obj).localTime) && this.height == ((Model) obj).height 81 && this.weight == ((Model) obj).weight; 82 } 83 84 @Override 85 public int hashCode() { 86 return Objects.hash(localTime, height, weight); 87 } 88 } 89} 90//------ 91//[{localTime=00:00, height=60, weight=90}, {localTime=00:00, height=60, weight=90}, {localTime=12:00, height=65, weight=90}, {localTime=12:00, height=70, weight=80}, {localTime=15:00, height=80, weight=90}, {localTime=15:00, height=80, weight=90}, {localTime=15:00, height=66, weight=190}, {localTime=15:00, height=55, weight=290}] 92//------ newList 93//[{localTime=00:00, height=60, weight=90}, {localTime=12:00, height=70, weight=80}, {localTime=15:00, height=80, weight=90}]

投稿2021/08/31 01:07

編集2021/08/31 02:54
shiketa

総合スコア4041

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

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

jimbe

2021/08/31 02:39

equals で toString を使っていることに関しまして、一応注意書きがあった方が良いように思いますが、如何でしょう。
shiketa

2021/08/31 02:56

本筋に関係なさそうだからまいいか、と端折りましたった。手直ししておきました。
jimbe

2021/08/31 03:24

お手数お掛けしてすいません。
xebme

2021/08/31 07:27

これは力作ですね。
shiketa

2021/08/31 08:52

ども f(^^; \# 最近はKotlinあたまなので、Java/Streamの煩わしさがヤでヤで... data classはうかんだのですが、recordはおもいうかばなかったです。それも含めて相当すっきりしますね。勉強になります。
guest

0

データ処理にランダムを入れてくるのが新鮮ですので、そのままコード化してみます。

java

1import java.time.LocalTime; 2import java.util.ArrayList; 3import java.util.List; 4import java.util.Random; 5 6class Model { 7 /** 時刻. */ 8 final LocalTime localTime; 9 /** 身長 */ 10 final int height; 11 /** 体重. */ 12 final int weight; 13 14 public Model(LocalTime localTime, int height, int weight) { 15 this.localTime = localTime; 16 this.height = height; 17 this.weight = weight; 18 } 19 20 @Override 21 public String toString() { 22 return new StringBuilder(super.toString()) 23 .append("[localtime=").append(localTime) 24 .append(",height=").append(height) 25 .append(",weight=").append(weight) 26 .append("]").toString(); 27 } 28} 29 30public class Q356940 { 31 public static void main(String[] args) { 32 List<Model> list = new ArrayList<>(); 33 34 Model a = new Model(LocalTime.of(0, 0), 60, 90); 35 Model b = new Model(LocalTime.of(0, 0), 60, 90); 36 Model c = new Model(LocalTime.of(12, 0), 65, 90); 37 Model d = new Model(LocalTime.of(12, 0), 70, 80); 38 Model e = new Model(LocalTime.of(15, 0), 80, 90); 39 Model f = new Model(LocalTime.of(15, 0), 80, 90); 40 41 list.add(a); 42 list.add(b); 43 list.add(c); 44 list.add(d); 45 list.add(e); 46 list.add(f); 47 for(Model m : list) System.out.println(m); 48 49 Random random = new Random(); 50 for (int i = 0; i < list.size(); i++) { 51 for (int j = i+1; j < list.size(); j++) { 52 //時刻比較(どちらかが消える) 53 if (list.get(i).localTime == list.get(j).localTime) { 54 //身長比較(小さいほうが消える) 55 if (list.get(i).height > list.get(j).height) { 56 list.remove(j--); continue; 57 } else if (list.get(i).height < list.get(j).height) { 58 list.remove(i--); break; 59 } 60 //体重比較(軽いほうが消える) 61 if (list.get(i).weight > list.get(j).weight) { 62 list.remove(j--); continue; 63 } else if (list.get(i).weight < list.get(j).weight) { 64 list.remove(i--); break; 65 } 66 //どっちでもいい(ランダムに消える) 67 if (random.nextInt(2) == 0) { 68 list.remove(j--); continue; 69 } else { 70 list.remove(i--); break; 71 } 72 } 73 } 74 } 75 76 System.out.println("----"); 77 for(Model m : list) System.out.println(m); 78 } 79}

plain

1Model@73a28541[localtime=00:00,height=60,weight=90] 2Model@470e2030[localtime=00:00,height=60,weight=90] 3Model@3fb4f649[localtime=12:00,height=65,weight=90] 4Model@33833882[localtime=12:00,height=70,weight=80] 5Model@200a570f[localtime=15:00,height=80,weight=90] 6Model@16b3fc9e[localtime=15:00,height=80,weight=90] 7---- 8Model@73a28541[localtime=00:00,height=60,weight=90] 9Model@33833882[localtime=12:00,height=70,weight=80] 10Model@200a570f[localtime=15:00,height=80,weight=90]

投稿2021/08/30 18:30

編集2021/08/30 18:40
jimbe

総合スコア13168

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

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

0

このような場合、Model側にcompareToメソッドを実装してデータ同士の大小関係を比較するのが定石になります。
専用のインターフェースがあります。
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Comparable.html

java

1 /** 2 * 引数のModelと比較する。時刻、身長、体重の順で大小を比較する 3 * 正の値が返れば、this側のオブジェクトの方が大きい。 4 * 負の値が返れば、other側のオブジェクトの方が大きい。 5 */ 6 public int compareTo(Model other){ 7 // まず時刻の比較 8 int comp; 9 comp = this.localTime.compareTo(other.getLocalTime()); 10 if(comp != 0) 11 return comp; 12 // 時刻が同じ(compが0)の場合、身長で比較 13 comp = this.height - other.getHeight(); 14 if(comp != 0) 15 return comp; 16 // 身長も同じ(compが0)の場合、体重で比較 17 return this.weight - other.getWeight(); 18 }

Main側ではまずリスト中の2つの要素について時刻を比較し、異なっていたらそのまま残す。
同じであれば、上記作成したcompareToメソッドで身長、体重を比較し、小さい方を削除するようにすれば良いでしょう。
(これは元のリストが時刻でソートされていることが前提になります)

java

1 for (int i = 0; i < list.size()-1; i++) { 2 Model m1 = list.get(i); 3 Model m2 = list.get(i+1); 4 // 2つの時刻が違っていたらそのまま残す 5 if(!m1.getLocalTime().equals(m2.getLocalTime())){ 6 continue; 7 }else{ 8 // 時刻が同じだったら、compareToメソッドで身長、体重の大小を比較 9 int comp = m1.compareTo(m2); 10 // compが正ならm1が大きいのでm2を削除、、compが負ならm2が大きいのでm1を削除 11 if(comp > 0){ 12 list.remove(m2); 13 i--; 14 }else if(comp < 0){ 15 list.remove(m1); 16 i--; 17 }else{ 18 // 同じだったらランダムで削除とのことだが、実装が面倒なのでm1を削除する 19 list.remove(m1); 20 i--; 21 } 22 } 23 }

paiza.ioでのデモ

投稿2021/08/30 14:23

hope_mucci

総合スコア4447

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

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

taro_11111

2021/08/30 15:48

すみません、comparetoが既に時刻を昇順に並び替える事で使用していました。。。
guest

0

先頭から順に探した場合、あるインデックスのものを削除すると、それ以降のものは順番が狂ってしまいます

こういう場合の鉄則は、後尾から先頭へ向かって探していくこと、です。
後ろからだと、削除してもそれ以降の順番は狂いません

投稿2021/08/30 13:58

y_waiwai

総合スコア88024

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問