木曜日, 5月 09, 2013

Commons Collection 1 - IterableMap, OrderedMap

便利!?

有難いライブラリを量産してくれているCommonsは,当然独自のcollectionも提供してくれている.
言うまでもなくこれらを知っておくことは大切だ,ということで何回かに分けてメジャーどころを紹介していくこととする.

IterableMap - イテレータが使えるマップ

ご存じのとおり,Javaの標準mapではイテレーションはサポートしていない.これが意外に不便だと思う時も少なくない.勿論イテレーションが出来ないわけじゃない.でもコードが大変不器用な感じになるのである.以下のように要素のセットをマップから取得しそのセットからイテレータを生成する,という流れである.

 @Test
 public void testMapIteration() {
  
  Map<Integer,String> map = initMap();
  Iterator<Entry<Integer,String>> entSet = map.entrySet().iterator();
  while( entSet.hasNext() ) {
   Entry<Integer,String> e = entSet.next();
   System.out.printf( "%d-%s\n", e.getKey(), e.getValue() );
  }
 }
 
 private Map<Integer,String> initMap() {
  Map<Integer,String> m = new HashMap<Integer,String>();
  m.put( 1, "NewYork" );
  m.put( 2, "Tokyo" );
  m.put( 3, "Bangalore" );
  m.put( 4, "London" );
  m.put( 5, "Paris" );
  return m;
 }


では一方でCommons Collectionが提供しているIterableMapを使うとどうなるか?
コードは以下のようになる.

 /**
  * Order not stable. Result is like .. 
  * <pre>
  * 2Tokyo
  * 4London
  * 1NewYork
  * 3Bangalore
  * 5Paris
  * </pre>
  */
 @Test
 public void testIterableMap() {
  
  IterableMap map = new HashedMap( initMap() );
  MapIterator iter = map.mapIterator();
  String val = null;
  int key = 0;
  
  while( iter.hasNext() ) {
   
   iter.next();
   key = ((Integer)iter.getKey()).intValue();
   val = (String)iter.getValue();
   System.out.printf("%d%s\n",key, val);
   
  }
 }

 private Map<Integer,String> initMap() {
  Map<Integer,String> m = new HashMap<Integer,String>();
  m.put( 1, "NewYork" );
  m.put( 2, "Tokyo" );
  m.put( 3, "Bangalore" );
  m.put( 4, "London" );
  m.put( 5, "Paris" );
  return m;
 }




まぁどっちがいいかは人の好みによるかもしれない(^_^;)

OrderedMap - 要素の順序が保障されるマップ

Mapにputした順序が維持されるマップである.便利そうだ..でもたちまちにユースケースが思いつかない..でもきっと役に立つ..と不思議な感覚に陥るマップである.
ここではLinkedMapという実装クラスを使用する.
また,以下の例ではもしかしたら陥るかもしれない,ちょっとした落とし穴を跨いでいる.
上記の通りこのマップはputをした順を保持する.気をつけたいのはLinkedMapをjava.util.Mapを引数にとるコピーコンストラクタを使う場合だ.当然java.util.Mapの要素の取り出される順序はハッシュの順なのでputした順とは違う.なので最初のmapのループのアウトプットはinitMap()でputした順序ではないのである.あくまでコピーコンストラクタの内部で取り出された順序,である.


 @SuppressWarnings("unchecked")
 @Test
 public void testOrderedMap() { 
  
  OrderedMap map = new LinkedMap( initMap() ); 
  MapIterator iter = map.mapIterator();
  String val = null;
  int key = 0;
  while( iter.hasNext() ) {
   
   iter.next();
   key = ((Integer)iter.getKey()).intValue();
   val = (String)iter.getValue();
   System.out.println(key + val);
   
  }
  map.clear();
  map.put( 1, "Metuchen" );
  map.put( 3, "Kosciuszko" );
  map.put( 2, "Kitami" );
  map.put( 5, "Tripoli" );
  map.put( 4, "Serangoon" );
  assertThat( ((Integer)map.firstKey()).intValue(), is( 1 ) );
  assertThat( (String)map.get(map.firstKey()), is( "Metuchen" ) );
  assertThat( ((Integer)map.nextKey(3)).intValue(), is( 2 ) );
  assertThat( (String)map.get(map.nextKey(3)), is( "Kitami" ) );
  
 }


 private Map<Integer,String> initMap() {
  Map<Integer,String> m = new HashMap<Integer,String>();
  m.put( 1, "NewYork" );
  m.put( 2, "Tokyo" );
  m.put( 3, "Bangalore" );
  m.put( 4, "London" );
  m.put( 5, "Paris" );
  return m;
 }






0 件のコメント: