複数のマップをひとつのマップインスタンスからアクセスできる,ビューのようなものを利用できれば便利だなぁ,と思ったことはないだろうか.そのようなユースケースに対してはCompositeMapを使うと良い.以下のコードはマップのユースケースだが,同じような機能がセット,ひいてはコレクションに対しても用意されている ( CompositeSet, CompositeCollection ).
注意しておきたいのは,重複したキーがあった場合にはCompositeクラスは例外をスローすることである.
@Test(expected=Exception.class) public void testCompositeMap() { CompositeMap compo = new CompositeMap( initMap(), initMap2() ); assertThat( compo.size(), is( 10 ) ); compo = new CompositeMap( initMap(), initMap() ); } 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; } private Map<Integer,String> initMap2() { Map<Integer,String> m = new HashMap<Integer,String>(); m.put( 6, "Hongkong" ); m.put( 7, "Seoul" ); m.put( 8, "Cairo" ); m.put( 9, "AllenTown" ); m.put( 10, "GeorgeTown" ); return m; }
FastList - 非同期リードを提供するリスト
Javadocにも書いてある通り,このクラスはマルチスレッド環境下で大半がリードアクセスである場合の使用を想定している.FastListを使った場合,リストへのリードアクセスは非同期化され,ライトアクセスは以下のような処理を経る.
- 既存のコレクションをクローン
- クローンに対して変更を適用
- 既存のコレクションをステップ2 で変更したクローンと置き換える
FastListには slow モードと fast モードの2つがあり,slowモードはリードアクセスは同期化され,ライト時のクローンも行われない.fastモードはリードは非同期,ライトもクローンプロセスを経る.
最初にこのクラスを生成したときはslowモードなので,最初の初期化が経てあとはほとんどリードオンリー,となった段階でsetFast(true)を呼ぶ必要がある.
ちなみにFast系は以下のコードで使っているFastArrayListのほかにFastHashMapとFastTreeMapがある.
コード
このコードはFastArrayListとArrayListの同じノードに対してそれぞれ100回アクセスした場合のラップタイムを計っている. 結果は何度やってもArrayListのほうが約2倍近く早い.おそらくFastArrayListは実装が色々と複雑となってしまっているのだろう.
import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.commons.collections.FastArrayList; import org.apache.commons.lang3.time.StopWatch; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; public class FastListTest implements Runnable { List<String> list = null; @Before public void init() { list = initFastList(); } @Test public void testFastList() throws InterruptedException { ExecutorService service = Executors.newFixedThreadPool( 30 ); StopWatch watch = new StopWatch(); watch.start(); for( int i = 0;i < 100;i++ ) { service.submit( this ); } service.shutdown(); service.awaitTermination( 10000L, TimeUnit.HOURS ); System.out.println( "FAST - " + watch.getTime() ); watch.reset(); list = initArrayList(); service = Executors.newFixedThreadPool( 30 ); watch.start(); for( int i = 0;i < 100;i++ ) { service.submit( this ); } service.shutdown(); service.awaitTermination( 10000L, TimeUnit.HOURS ); System.out.println( "NONFAST - " + watch.getTime() ); } private FastArrayList initFastList() { // slow mode first FastArrayList list = new FastArrayList(); list.add( "a" ); // switching to fast mode list.setFast( true ); return list; } private List<String> initArrayList() { // slow mode first List<String> list = new ArrayList<String>(); list.add( "a" ); // switching to fast mode return list; } public void run() { // access to random node list.get( 0 ); } }
0 件のコメント:
コメントを投稿