51342


データベースの全レコードを格納したListから  
「指定のフィールドに特定の文字列を含むデータ」を取り除くメソッドを  
実装したいのですが、どのように記述すればよろしいでしょうか。  
自分で下記のように記述してみたのですが、500エラーとなりました。恐れ入りますがご教示ください。  
※データベースについてはJPAを利用してDTOを実装しています。

* * *
[code]

    import Sample;　//その他必要なクラスをimport済
    
    //--メインメソッド内--
    List<Sample> samples　//へデータベースの全レコードを格納済
    String keyword　//へ特定の文字列を格納済
    
    samples = keyList(samples, keyword);
    
    //--メインメソッドのブロック外に目的のメソッドを記述--
    public List<Sample> keyList(List<Sample> list, String keyword) {
        List<Sample> newList = list;
        for(Sample sample : list) {
            if (sample.指定のgetter().contains(keyword)) {
                newList.remove(sample);
            }
        }
        return newList;
    }
    
[/code]


CC BY-SA 4.0
2018-12-18T03:30:56.210
51317
2019-01-04T09:05:07.207
2018-12-18T23:51:45.203
31502
31502
question
java
指定のフィールドに特定の文字列を含むデータを取り除くメソッドを実装したい


発生している例外は[`ConcurrentModificationException`](https://docs.oracle.com/javase/jp/8/docs/api/java/util/ConcurrentModificationException.html)ではないかと想像します。  
この例外は、質問文中コードで言うと

[code]

    for(Sample sample : list) {
            ...
                newList.remove(sample);
        }
    }
    
[/code]

のように、リストを`for`ループで順繰りに処理している最中(反復処理中)にリストの要素を減らしたり増やしたりすると発生します。

[code]

    List<Sample> newList = list;
    
[/code]

でなく、

[code]

    List<Sample> newList = new ArrayList<>(list);
    
[/code]

とすれば、`list`と`newList`で異なるリストを参照することになるので前述「反復処理中の要素増減」は回避できます(ループさせているリストと要素を減らしているリストは別物なので)。

ただ、反復処理を行うには通常[`Iterator`](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Iterator.html)を用います。

Java8以降であれば[`Collection#removeIf`メソッド](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Collection.html#removeIf-
java.util.function.Predicate-)が利用できます:

[code]

    List<Sample> newList = new ArrayList<>(list);
    newList.removeIf(sample -> sample.指定のgetter().contains(keyword));
    return newList;
    
[/code]

古典的な書き方であれば、

[code]

    List<Sample> newList = new ArrayList<>(list);
    Iterator<Sample> ite = newList.iterator();
    while (ite.hasNext()) {
        Sample sample = ite.next();
        if (sample.指定のgetter().contains(keyword)) {
            ite.remove();
        }
    }
    return newList;
    
[/code]

となります。


CC BY-SA 4.0
2018-12-19T01:28:03.053
51342
2018-12-19T02:20:57.253
2018-12-19T02:20:57.253
2808
2808
51317
answer


メソッドなかで、渡されたリスト中のエレメントを弄ったら、不具合につながる可能性があるので、変更しないほうが安全です。

[code]

    public List<Sample> keyList(List<Sample> list, String keyword) {
        List<Sample> newList = new ArrayList<>(list.size());
        for(Sample sample : list) {
            if (sample.指定のgetter().contains(keyword)) {
                newList.add(sample);
            }
        }
        return newList;
    }
    
[/code]


CC BY-SA 4.0
2019-01-04T09:05:07.207
51700
2019-01-04T09:05:07.207
23688
51317
answer