複数のマップをひとつのマップインスタンスからアクセスできる,ビューのようなものを利用できれば便利だなぁ,と思ったことはないだろうか.そのようなユースケースに対しては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 件のコメント:
コメントを投稿