2016-04-19 2 views
1

私はコレクション内の要素を新しい修正版に置き換えようとしています。以下は私が達成したいことを実証することを目的とする短いコードです。Javaコレクションのオブジェクトを置き換えるにはどうしたらいいですか?

全体的なアイデアは、私は他のオブジェクトのコレクションで構成されて一つのオブジェクトを持っているということです。ある時点では、コレクションのこのオブジェクト(私の電話機の場合)にいくつかの変更が必要な場合があり、コードを1か所だけ変更したいと思っています。

私は、以下に示すようコレクションを反復しながら、オブジェクトの属性を更新するために、私はセッターを使用することができることを知っています。しかし、おそらくそれを達成するためのより良い、より一般的な方法があります。

public class Customer { 
    private int id; 
    private Collection<Phone> phoneCollection; 
    public Customer() { 
     phoneCollection = new ArrayList<>(); 
    } 
//getters and setters  

} 

と電話クラス

public class Phone { 
    private int id; 
    private String number; 
    private String name; 
//getters and setters  
} 

public static void main(String[] args) { 
     Customer c = new Customer(); 

     c.addPhone(new Phone(1, "12345", "aaa")); 
     c.addPhone(new Phone(2, "34567", "bbb")); 
     System.out.println(c); 

     Phone p = new Phone(2, "9999999", "new name"); 

     Collection<Phone> col = c.getPhoneCollection(); 
     for (Phone phone : col) { 
      if (phone.getId() == p.getId()) { 
//    This is working fine 
//    phone.setNumber(p.getNumber()); 
//    phone.setName(p.getName()); 

//    But I'd like to replace whole object if possible and this is not working, at least not that way 
        phone = p; 
      } 
     } 
     System.out.println(c); 
    } 
} 

これは私が欲しいものを達成することは可能ですか? 私はコピーコンストラクタのアイデアと私はネットを検索見つかった他の方法を試してみましたが、私が期待するようにそれらのどれも働いていませんでした。

EDIT 1

いくつかのコメントを読んだ後、私は

が、私は自分の携帯電話のクラスに次のメソッドを追加したアイデアを得た

public static void replace(Phone org, Phone dst){ 
    org.setName(dst.getName()); 
    org.setNumber(dst.getNumber()); 
} 

、今の私のforeach部分はその

のように見えます
for (Phone phone : col) { 
     if (phone.getId() == p.getId()) { 
      Phone.replace(phone, p); 
     } 
    } 

と私仕事をしません。 Phoneクラスの属性を変更すると、そのメソッドを変更するだけで済みます。そうした問題を解決することは問題ないと思いますか?代わりに、リストの

+0

いいえ、これはできません。コレクションが変更不可能な場合、そのコレクションはどのように機能すると思いますか? –

+0

'foreach'が読み取り専用のループで、' phone'への参照を変更できないので、うまく動作しませんでした – Andrew

答えて

0

、キーとして電話のIDでmapを使用しています。次に、あなたのコードは次のようになります。あなたに注文事項は、あなたが(あなたが常にとにかくArrayListを使用しているので)ListCollectionを変更することができた場合

public static void main(String[] args) { 
     Customer c = new Customer(); 

     c.addPhone(new Phone(1, "12345", "aaa")); 
     c.addPhone(new Phone(2, "34567", "bbb")); 
     System.out.println(c); 

     Phone p = new Phone(2, "9999999", "new name"); 

     Map<Integer, Phone> phoneMap = c.getPhoneMap(); 
     phoneMap.put(p.getId(), p); 

     System.out.println(c); 
} 
+0

私はこのアイデアが大好きですが、単に 'phoneMap.put(p)'ではないのですか? – user949300

+0

意味があり、編集されています。 –

+0

私は自分のエンティティにリスト(またはコレクション)を持っており、それに固執したいと思います。私はいくつかの基本的な属性と多くのコレクション/リストで構成されるオブジェクトを更新するための最も簡単な反復可能なメソッドを探しています。これらのリストはJSFコンポーネントにバインドされています。 – norbi771

-2

int index = col.indexOf(phone); 
col.remove(phone); 
col.add(p, index); 
+1

問題は、彼は削除する電話を持っている、ちょうど電話のIDです。 – user949300

+0

彼は強化された 'for'ループを使用しています。これは彼に' Phone'を与えます。 'col.remove(index);' – Zircon

+0

でも可能ですが、 'col.indexOf(theNewPhone)'は常に-1を返します。彼がPhoneと同等のものを上書きしない限り。 – user949300

3

あなたはいけませんコレクションの反復処理中にコレクションを変更します。それがConcurrentModificationExceptionになる可能性があります。検索条件に一致する最初のオブジェクトのコレクションをスキャンできます。その後、ループを終了して古いオブジェクトを削除し、新しいオブジェクトを追加することができます。

Collection<Phone> col = c.getPhoneCollection(); 
Phone original = null; 
for (Phone phone : col) { 
    if (phone.getId() == p.getId()) { 
     original = phone; 
     break; 
    } 
} 
if (original != null) { 
    Phone replacement = new Phone(original); 
    replacement.setNumber(p.getNumber()); 
    replacement.setName(p.getName()); 
    col.remove(original); 
    col.add(replacement); 
} 

また、あなたは交換用のステップは、はるかに効率的になるだろう、インデックス、で動作するようにできるようになること、などListとして、コレクションのより具体的な型を宣言することができます。

お使いの携帯電話のIDは各電話に固有のものである場合は、対応する携帯電話に各電話番号をマップMap<Integer, Phone>の使用を検討すべきです。(あるいは、各IDをボックス化することを伴わないサードパーティのスパース配列構造をIntegerに使用することもできます)。もちろん、IDが一意でない場合は、上記を修正してすべての一致する電話の二次収集(既存のコードのロジックも再考します)。

+0

2世代目のループの外側で置換えが作成された場合、IMHOはややクリーナーになります。たぶん元の名前に変更されていますか? – user949300

+0

'ConcurrentModificationException'を回避しながら、イテレータを使ってイテレーションを削除する方が簡単です。 – MeetTitan

+0

すべてのサブクラスで 'remove'メソッドが実装されているわけではありません(' default'でこの例外をスローします)。 – Andrew

-1

オブジェクトをコレクションから取り出してそのプロパティを更新すると、コレクション内の同じオブジェクトにも反映されます。したがって、オブジェクトを更新した後は、技術的にオブジェクトを置き換える必要はありません。 「Mike M.」としてハッシュマップを使用して反復せずにオブジェクトをすばやく取得し、オブジェクト値を更新することができます。

+0

それはOPがすでにやっていることです。問題は、具体的には、コレクション内の既存のオブジェクトを変更することではありません。 –

1

また、Set(HashSet)を使用することもできます。これは、Mikeが提案したやり方をしたくない場合にのみ有効です。

電話機をセット内のアイテムとして使用します。 PhoneでhashCode()とequals()を実装することを忘れないでください。 hashCode()は一意であるはずなので、idを返すべきです。

アイテムの交換について懸念しているので、ここでのHashSetのはあなたを助ける方法は次のとおりです。

  1. あなたのオブジェクトのインスタンスを作成します。
  2. 置き換えたいオブジェクトをセットから削除します。
  3. 新しいオブジェクト(手順1で作成したもの)をセットに追加して戻します。

これらの操作はいずれも、O(1)/一定時間で保証されます。

この問題のためにマップを維持する必要はありません。それは冗長です。

オブジェクトをコレクション自体から取得して変更したい場合は、HashMapのほうがいいでしょう。検索はO(1)時間で保証されます。

+0

これは彼が彼のコレクションの重複を否定しようとしていた場合にのみ役に立ちます。 – MeetTitan

+0

HashMapを使うのは基本的に同じことです。重複は許可されません。 – Partha

+0

しかし、重複した要素を排除することが目的でない限り、この場合リストにはどのような利点がありますか? – MeetTitan

関連する問題