0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GroovyのRangeを理解する

Posted at

GroovyとRubyのRangeの違いを前に書きましたが、その関係でGroovyのRangeについても調べたのでまとめます。

基本

ドキュメント

Rangeとは

シーケンシャルな値のリストを保持できるもの。java.util.List を拡張しているので、Listっぽいアクセスの仕方ができる。
ちなみに、Range自体はインターフェースで、実装としては EmptyRange, IntRange, ObjectRangeがある。

インスタンス生成

生成方法

Groovy
def range = 1..5
assert range == [1, 2, 3, 4, 5]

..だと、終端(上記のコードだと5)を含むRange、..<だと終端を含まないRangeを作成できる。

生成されるインスタンスの型について

ちなみに、どのRangeにするかによって、生成されるインスタンスの型が異なる。

Groovy
def intRange = 1..5
assert range instanceof IntRange

def objectRange = "a".."f"
assert objectRange instanceof ObjectRange

def emptyRange = new EmptyRange()
assert emptyRange instanceof EmptyRange

EmptyRangenewしないとダメっぽい。
参考:http://stackoverflow.com/questions/15485141/empty-groovy-range

アクセス

Listっぽくアクセス

Listを継承しているので、こんな感じにアクセスできる。

Groovy
def range = 1..5
assert range.size() == 5
assert range.get(2) == 3
assert range[2] == 3
assert range.contains(5)
assert !range.contains(6)

Rangeの中身を変えるアクセスは不可(つまりimmutable)

java.lang.Listを継承しているので、add()remove()といった、Rangeの内容を変更できそうなメソッドが定義されているけど、これらを呼び出そうとすると UnsupportedOperationException を投げる。

この理由は、ObjectRangejava.util.AbstractListを、IntRangeは、java.util.AbstractList<Integer>を継承しているため。
参考:http://stackoverflow.com/questions/24889972/why-does-range-throw-unsupportedoperationexception

また、この「サポートされないオペレーションの時はUnsupportedOperationExceptionを投げる」という仕様は、Listインターフェースに記載されている。
参考:https://docs.oracle.com/javase/jp/8/docs/api/java/util/List.html

イテレーション

eachメソッドを使って走査できる。

Groovy
(1..5).each {
    println "Hello ${i}"
}

swithの条件として使う

ドキュメント見て知ったけど、switchの条件判定に使える。

Groovy
switch (age) {
    case 1..<6: println "未就学"
    case 6..22: println "学生"
    default: println "卒業" 
}

拡張

独自クラスのRangeを自作する

作成するには、比較のためにjava.lang.Comparableを実装することと、next()previous()メソッドを実装する必要がある。

EnumはRangeにできる

Groovyは、JavaのEnum(Comparable実装済み)に next()previous()を付け加える。このため、EnumのRangeを作ることができる。

Groovy
enum DayOfWeek {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

def dayRange = DayOfWeek.SUNDAY..DayOfWeek.WEDNESDAY
assert dayRange.size() == 4
assert dayRange.contains(DayOfWeek.MONDAY)
assert !dayRange.contains(DayOfWeek.THURSDAY)

参考:http://mrhaki.blogspot.jp/2009/09/groovy-goodness-keep-your-values-in.html

Range、いろいろ便利だ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?