-
- Page 2
強化版のforを試す
強化版のforループはとても便利です。コードが簡潔になると同時に表現力も向上するので、申し分なしです。ただし、まだ足りない部分もあります。数字の0から9まで処理を反復するとしたら、古いCスタイルのforループ構文をいまだに使う必要があります。
for (int i = 0; i < 9; i++) ...
では、この範囲を新しい抽象表現にしてみたらどうでしょうか。
Sequence s = new Sequence(0, 9);
このSequenceクラスにIterable<Integer>を実装しておけば、強化版のforループで次の記述が可能になります。
for (int i: new Sequence(0, 9)) ...
オートアンボクシングが追加されたため、クライアントインターフェースは非常に簡潔になります。リスト1に、Sequenceクラスの完全なコードを示します。
import java.util.Iterator;
public class Sequence implements Iterable<Integer> {
private int start;
private int stop;
private int increment = 1;
public Sequence(int start, int stop) {
this.start = start;
this.stop = stop;
}
public Sequence(int start, int stop, int increment) {
this(start, stop);
this.increment = increment;
}
public Iterator<Integer> iterator() {
return new SequenceIterator();
}
private class SequenceIterator implements Iterator<Integer> {
private int count = start;
public boolean hasNext() {
return count <= stop;
}
public Integer next() {
int result = count;
count += increment;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
このSequenceクラスには、要素をスキップする機能もあります。Sequenceクラスのさまざまな使用例をリスト2に示します。
import static org.junit.Assert.*;
import org.junit.*;
import java.util.*;
public class SequenceTest {
private List<Integer> ints;
@Before
public void createCollection() {
ints = new ArrayList<Integer>();
}
@Test
public void singleEntry() {
verifySequence(new Sequence(0, 0), 0);
}
@Test
public void twoEntries() {
verifySequence(new Sequence(1, 2), 1, 2);
}
@Test
public void multipleEntries() {
verifySequence(new Sequence(5, 10), 5, 6, 7, 8, 9, 10);
}
@Test
public void negativeNumbers() {
verifySequence(new Sequence(-2, 2), -2, -1, 0, 1, 2);
}
@Test
public void increment() {
verifySequence(new Sequence(0, 5, 2), 0, 2, 4);
}
@Test
public void incrementIncludesLimit() {
verifySequence(new Sequence(0, 6, 2), 0, 2, 4, 6);
}
private void verifySequence(Sequence sequence,
int... expectedValues) {
for (int i: sequence)
ints.add(i);
assertEquals(expectedValues.length, ints.size());
for (int i: expectedValues)
assertTrue(ints.contains(i));
}
}
どこにメリットがあるのでしょうか?まず、コードが簡潔になります。また、Sequenceがオブジェクトであることに利点があります。シーケンスを受け渡す(そして永続化する)ことができるのです。範囲やその他の情報を表す具体的な数字(ステップ値など)を受け渡さなければならないのとは大違いです。また、シーケンスを使用するコードを変更せずに機能を拡張できます。例えば、シーケンスを一時停止し、後でその位置から再開することもできるでしょう。
反復は、ありふれたコンピューティング処理の1つです。簡潔で、なおかつ一貫性と表現力のある実装方法が求められる状況には、反復はまさにうってつけです。Sunはこれまでに三度にわたってJavaコレクション反復メカニズムを作り出し、そのたびに改良を加えました。近い将来、また新しいメカニズムが登場することは間違いないでしょう。
この記事は参考になりましたか?
既に会員の方はを行ってください。
- デザインパターンの使い方連載記事一覧
-
- デザインパターンの使い方:Iterator
- デザインパターンの使い方: Abstract Factory
- デザインパターンの使い方: Prototype
- この記事の著者
-
japan.internet.com(ジャパンインターネットコム)
japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
Jeff Langr(Jeff Langr)
本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
