Eclipse Collections 10.0の新機能 - Part 3 #EclipseCollections

本記事はDonald Raab氏による New Features of Eclipse Collections 10.0 — Part 3 - Donald Raab - Medium を元にした日本語版の記事です。日本語でわかりやすい情報となるように適宜編集しており、日本語訳とは違って必ずしも元の文章を訳したものではありません(本人にrewriteの許可をもらっております)。原文を参考にしたい場合は上記リンクからどうぞ。

Eclipse Collections 10.0の新機能を用いたコード例を紹介していきます。 f:id:itohiro73:20190804234137p:plain

f:id:itohiro73:20190804234228p:plain
Eclipse Collections 10.0の新機能、最後の6個

サマリー

本記事では、Eclipse Collections 10.0がリリースされました #EclipseCollections - itohiro73’s blog で挙げた26個の新機能のうち、最後の6個を紹介します。Part 1では、最初の10個、Part 2では次の10個の新機能を例とともに紹介しました。

21. RichIterable.getAnyの実装

getAny メソッドは、順序の保証なくコレクションの最初の要素を返します。 このメソッドは、もともと RichIterable で提供されていて、順序保証がされていないコレクションで非推奨となった getFirst メソッドの代替となります。

@Test
public void getAny()
{
    Interval interval = Interval.fromTo(100, 1);
    Integer anyList =
            Lists.mutable.withAll(interval).getAny();
    Integer anySet =
            Sets.mutable.withAll(interval).getAny();
    Integer anyBag =
            Bags.mutable.withAll(interval).getAny();
    Integer anyStack =
            Stacks.mutable.withAll(interval).getAny();
    Assert.assertEquals(Integer.valueOf(100), anyList);
    Assert.assertEquals(Integer.valueOf(1), anySet);
    Assert.assertEquals(Integer.valueOf(1), anyBag);
    Assert.assertEquals(Integer.valueOf(1), anyStack);
}

22. プリミティブのハッシュデータ構造におけるresize/rehashメソッドの刷新と標準化

これは新機能というよりは改善ですが、全てのプリミティブのハッシュデータ構造に影響するので、ハイライトするに値するものかと思います。 変更の大部分はハッシュデータ構造の rehashAndGrow メソッドにあります。

バージョン9.2

private void rehashAndGrow()
{
    this.rehash(this.table.length << 1);
}

バージョン10.0

private void rehashAndGrow()
{
    int max = this.maxOccupiedWithData();
    int newCapacity = Math.max(max, smallestPowerOfTwoGreaterThan((this.occupiedWithData + 1) << 1));
    if (this.occupiedWithSentinels > 0 && (max >> 1) + (max >> 2) < this.occupiedWithData)
    {
        newCapacity <<= 1;
    }
    this.rehash(newCapacity);
}

23. Iterable<BoxedPrimitive>からPrimitiveStack/Bag/List/Setへ変換するファクトリメソッドの実装

Eclipse Collections 10.0以前では、ボックスされたプリミティブ型の Iterable をプリミティブコレクションに変換するには、まずは IterableCollection または Stream に変換する必要がありました。 Stream の場合は、 Collectors2 で提供されていたプリミティブCollectorでプリミティブのコレクションに変換する必要がありました。 バージョン10.0からは、以下のようなファクトリメソッドを用いて Iterable からプリミティブコレクションを直接生成することができます。 この機能は、全てのボックスされたプリミティブ型 Iterable から、全てのプリミティブのコレクション型に対応しています。

@Test
public void convertFromIterableToPrimitiveCollection()
{
    Iterable<Integer> iterable = Interval.oneTo(5);
    IntInterval intInterval = IntInterval.oneTo(5);
    MutableIntList mIntList = 
            IntLists.mutable.withAll(iterable);
    ImmutableIntList iIntList = 
            IntLists.immutable.withAll(iterable);
    Assert.assertEquals(intInterval, mIntList);
    Assert.assertEquals(intInterval, iIntList);
    MutableIntSet mIntSet = 
            IntSets.mutable.withAll(iterable);
    ImmutableIntSet iIntSet = 
            IntSets.immutable.withAll(iterable);
    Assert.assertEquals(intInterval.toSet(), mIntSet);
    Assert.assertEquals(intInterval.toSet(), iIntSet);
    MutableIntBag mIntBag = 
            IntBags.mutable.withAll(iterable);
    ImmutableIntBag iIntBag = 
            IntBags.immutable.withAll(iterable);
    Assert.assertEquals(intInterval.toBag(), mIntBag);
    Assert.assertEquals(intInterval.toBag(), iIntBag);
}

24. Multimapsファクトリクラス内の'ImmutableSortedBagMultimapFactory`の実装

Multimaps クラスには、しばらく ImmutableSortedBagMultimapFactory が提供されていませんでした。バージョン10.0でこちらの機能がついに追加されましたが、名前付けに問題があり現在issueが挙げられています。

Variable name in Multimaps class for ImmutableSortedBagFactory is incorrect · Issue #737 · eclipse/eclipse-collections · GitHub

25. MapをパラメータにとるMapファクトリメソッドの実装

Map もしくは MapIterableMaps ファクトリメソッドにわたして MutableMap を生成することができるようになりました。

@Test
public void mapFactoryThatTakesMapAsParameter()
{
    MutableMap<Integer, Integer> mutableSource =
            Maps.mutable.with(1, 1, 2, 2, 3, 3);
    ImmutableMap<Integer, Integer> immutableSource =
            Maps.immutable.with(1, 1, 2, 2, 3, 3);
    Assert.assertEquals(mutableSource, immutableSource);
    MutableMap<Integer, Integer> mutableOf =
            Maps.mutable.ofMap(mutableSource);
    MutableMap<Integer, Integer> mutableWith =
            Maps.mutable.withMap(mutableSource);
    Assert.assertEquals(mutableSource, mutableOf);
    Assert.assertEquals(immutableSource, mutableWith);
    MutableMap<Integer, Integer> mutableOfMI =
            Maps.mutable.ofMapIterable(immutableSource);
    MutableMap<Integer, Integer> mutableWithMI =
            Maps.mutable.withMapIterable(immutableSource);
    Assert.assertEquals(immutableSource, mutableOfMI);
    Assert.assertEquals(immutableSource, mutableWithMI);
}

26. MultableMultimap.putAllPairs/addメソッドパラメーターへのワイルドカード型の導入

こちらはふたつの putAllPairs メソッドと、 add(Pair) メソッドのジェネリクスの変更になります。 Pair型に ? extendsワイルドカード型が足されました。

boolean add(Pair<? extends K, ? extends V> keyValuePair)
boolean putAllPairs(Pair<? extends K, ? extends V>... pairs)
boolean putAllPairs(Iterable<? extends Pair<? extends K, ? extends V>> pairs)

使用例

@Test
public void wildcardInMutableMultimapPutAllPairs()
{
    MutableListMultimap<CharSequence, CharSequence> multimap =
            Multimaps.mutable.list.empty();
    multimap.add(Tuples.pair("1-5", "1"));
    multimap.putAllPairs(
            Tuples.pair("1-5", "2"),
            Tuples.pair("1-5", "3"));
    multimap.putAllPairs(
            Lists.mutable.with(
                    Tuples.pair("1-5", "4"),
                    Tuples.pair("1-5", "5")));
    Multimap<String, String> expected =
            Interval.oneTo(5)
                    .collect(Object::toString)
                    .groupBy(e -> "1-5");
    Assert.assertEquals(expected, multimap);
}

以上です

以上でEclipse Collections 10.0の新機能をすべてご紹介しました。

Eclipse Collections 10.0の新機能、楽しんでいただけると幸いです!!

Eclipse Collectionsコントリビューションを受け付けています!どこから始めていいかよくわからないという方はitohiro73までDMいただければ喜んでガイドさせていただきます。

もしライブラリを気に入っていただけて、われわれに知らせたいという方は、Twitterハッシュタグ#EclipseCollectionsをつけてつぶやいていただいたり、もしくはGitHubレポにスターをつけていただけるとめっちゃよろこびますのでどうぞよろしくお願いします!!