投影、过滤、选择

ognl可以对所有对象进行投影、过滤、选择,不同类型遍历方式可分为如下方式:

类型 遍历方式
数组 按照数组索引从小到大遍历
Iterator/Iterable/Enumeration子类 按照迭代器遍历
Map子类 按照Map的值的迭代器遍历,即map.values().iterator()
数字类型 从0开始到小于给定数字的正整数部分
其他对象 按照单个对象集合遍历,即只有当前对象的一个元素的集合

投影

投影语法obj.{ function }

类似java中Stream的map操作,将集合元素投影为其他对象集合。

# 数组投影 类似Stream.of(values).map(...).collect(Collectors.toList())
[arthas@9912]$ ognl 'new int[]{1, 2, 3}.{ #this*#this }'
@ArrayList[
    @Integer[1],
    @Integer[4],
    @Integer[9],
]

# 集合投影 类似collection.stream().map(...).collect(Collectors.toList())
[arthas@9912]$ ognl '{1, 2, 3}.{ -#this*#this }'
@ArrayList[
    @Integer[-1],
    @Integer[-4],
    @Integer[-9],
]

# Map投影 类似map.values().stream().map(...).collect(Collectors.toList())
[arthas@9912]$ ognl '#{"a": "A", "b": "B"}.{ #this + #this }'
@ArrayList[
    @String[AA],
    @String[BB],
]

# 数字类型投影 类似IntStream.rangeClose(0, 6).map(...).collect(Collectors.toList())
[arthas@9912]$ ognl 'new Integer(6).{ #this + 1 }'
@ArrayList[
    @Integer[1],
    @Integer[2],
    @Integer[3],
    @Integer[4],
    @Integer[5],
    @Integer[6],
]

# 其他类型投影 类似Stream.of(object).map(...).collect(Collectors.toList())
[arthas@9912]$ ognl '@System@out.{ "aaa" }'
@ArrayList[
    @String[aaa],
]

过滤

过滤语法object.{? predicat }

类似java中Stream的filter操作,从集合中过滤满足条件的对象集合。

# 数组过滤 类似Stream.of(values).filter(...).collect(Collectors.toList())
[arthas@9912]$ ognl 'new int[]{1, 2, 3}.{? #this > 2 }'
@ArrayList[
    @Integer[3],
]

# 集合投影 类似collection.stream().filter(...).collect(Collectors.toList())
[arthas@9912]$ ognl '{1, 2, 3}.{? #this > 2 }'
@ArrayList[
    @Integer[3],
]

# Map投影 类似map.values().stream().filter(...).collect(Collectors.toList())
[arthas@9912]$ ognl '#{"a": "A", "b": "B"}.{? #this == "A" }'
@ArrayList[
    @String[A],
]

# 数字类型投影 类似IntStream.rangeClose(0, 6).filter(...).collect(Collectors.toList())
[arthas@9912]$ ognl 'new Integer(6).{? #this % 2 == 1 }'
@ArrayList[
    @Integer[1],
    @Integer[3],
    @Integer[5],
]

# 其他类型投影 类似Stream.of(object).filter(...).collect(Collectors.toList())
[arthas@19040]$ ognl '@System@out.{? #this.checkError }'
@ArrayList[isEmpty=true;size=0]

选择

选择第一个语法object.{^ predicat }

选择最后一个语法object.{$ predicat }

类似java中Stream的findFirst,找到第一个或最后一个满足条件的集合(虽然只找一个,返回结果还是集合类型)对象。

# 数组选择
[arthas@19040]$ ognl 'new int[]{1, 2, 3}.{^ #this > 1 }'
@ArrayList[
    @Integer[2],
]
[arthas@19040]$ ognl 'new int[]{1, 2, 3}.{$ #this > 1 }'
@ArrayList[
    @Integer[3],
]

# 集合选择
[arthas@19040]$ ognl '{1, 2, 3}.{^ #this > 1 }'
@ArrayList[
    @Integer[2],
]
[arthas@19040]$ ognl '{1, 2, 3}.{$ #this > 1 }'
@ArrayList[
    @Integer[3],
]

# Map选择
[arthas@9912]$ ognl '#{"a": "A", "b": "BB", "c": "CCC" }.{^ #this.length > 1 }'
@ArrayList[
    @String[BB],
]
[arthas@9912]$ ognl '#{"a": "A", "b": "BB", "c": "CCC" }.{$ #this.length > 1 }'
@ArrayList[
    @String[CCC],
]

# 数字选择
[arthas@19040]$ ognl 'new Integer(6).{^ #this % 2 == 1 }'
@ArrayList[
    @Integer[1],
]
[arthas@19040]$ ognl 'new Integer(6).{$ #this % 2 == 1 }'
@ArrayList[
    @Integer[5],
]

# 单个对象选择没啥意义等同于单个对象的过滤