class Person {
String name
final int age
}
05 五月 2018
本文旨在对有 java 基础的程序员在几分钟内了解 groovy 不同于 groovy 的技巧, 方便快速使用到 groovy 带来的便捷.
每句语法后不需要分号
兼容绝大多数 java 语法
非强类型语言, 使用推导类型, 可以使用 def
来定义变量
class Person {
String name
final int age
}
属性和对象默认为 public
属性会自动生成 getter 和 setter.
调用 person.name
等同于调用 person.getName()
final 只有 get 方法.
可以使用带参数名的构造方法
def person = new Person(name: "John", age: 18)
方法调用可以不写括号, 下面两句是一样的
println("haha")
println "haha"
person.name ?: 'default name' person.school?.name ?: 'null school or null name'
groovy 中字符串字面量有两种:
def s1 = "world"
def s2 = "hello $s1"
assert s2 == "hello world" // true
s1 是 String 类型, s2 是 GString 类型, 因为 s2 中有 $
形式的插入值
觉大多数情况下, 可以忽略两种类型的差异.
groovy 中字符串可以通过 ==
来判断字符串相等.
单引号 '
的字符串, 就是纯字符串 java.lang.String
双引号 "
的字符串, 可以有插入值, 如 assert "hello $1" == "hello world"
三引号 '''
和 """
, 是多行形式, 比如
def s1 = """hello
world"""
groovy 提供了方便的 list 定义方式, 这个方式的 list 默认是 ArrayList 形式
// 定义 list
def letters = ['a', 'b', 'c', 'd']
assert letters[0] == 'a'
assert letters[1] == 'b'
assert letters[-1] == 'd'
assert letters[-2] == 'c'
letters[2] = 'C'
assert letters[2] == 'C'
// 添加一个元素
letters << 'e'
assert letters[ 4] == 'e'
assert letters[-1] == 'e'
// 根据下标取子集
assert letters[1, 3] == ['b', 'd']
// 根据范围去子集
assert letters[2..4] == ['C', 'd', 'e']
groovy 提供了方便的 map 定义方式, 这个方式的 map 默认是 LinkedHashMap 形式
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF']
assert colors['red'] == '#FF0000'
assert colors.green == '#00FF00'
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
assert colors.pink == '#FF00FF'
assert colors['yellow'] == '#FFFF00'
assert colors instanceof java.util.LinkedHashMap
java8 的 stream 操作带来很多便利, groovy 除了能使用 java8 的 stream 外, 还有自己的一套更为方便的流式操作
['a', 'b', 'c'].each { it -> println "$it" } ['a', 'b', 'c'].eachWithIndex { it, i -> println "$i: $it" }
def list = [1, 2, 3, 4, 5]
assert list.grep {it > 3} == [4, 5]
def list = [1, 2, 3, 4, 5]
assert list.collect { (it * 2) as String } == ["2", "4", "6", "8", "10"]
assert [
[name: 'Clark', city: 'London'], [name: 'Sharma', city: 'London'],
[name: 'Maradona', city: 'LA'], [name: 'Zhang', city: 'HK'],
[name: 'Ali', city: 'HK'], [name: 'Liu', city: 'HK'],
].groupBy { it.city } == [
London: [[name: 'Clark', city: 'London'],
[name: 'Sharma', city: 'London']],
LA : [[name: 'Maradona', city: 'LA']],
HK : [[name: 'Zhang', city: 'HK'],
[name: 'Ali', city: 'HK'],
[name: 'Liu', city: 'HK']],
]
// 对于常见的把一个列表建立 id 索引
assert [
[id: 1, name: 'Clark', city: 'London'], [id: 2, name: 'Sharma', city: 'London'],
[id: 3, name: 'Maradona', city: 'LA']
].groupBy { it.id }.collectEntries { key, value -> [key, value.first] } == [
1: [id: 1, name: 'Clark', city: 'London'],
2: [id: 2, name: 'Sharma', city: 'London'],
3: [id: 3, name: 'Maradona', city: 'LA']
]
new File("a.txt").eachLine { line ->
println line
}
def out = new File("out.txt")
out << "hello world\n"
out << "something"
File data = new File(fileName)
data.newReader("GBK").lines().skip(1).each { line ->
out << line << "\n"
}
看例子
if(args.size() < 1 ) {
println "need pid"
return
}
def pid = args[0]
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = "top -b -n 1 -H -p ${pid}".execute()
proc.consumeProcessOutput(sout, serr)
proc.waitFor()
def begin = false
def countLimit = 10
def count = 0
sout.eachLine { line ->
if (line.trim().size() == 0) {
return
}
if (begin && count <= countLimit) {
println line
def row = line.trim().split(" +")
def tid = String.format("nid=0x%x", row[0].toInteger())
println tid
def sout1 = new StringBuilder(), serr1 = new StringBuilder()
def p1 = (System.getenv("JAVA_HOME")+"/bin/jstack -l ${pid} ").execute() | ["grep", tid ,"-A 20"].execute()
p1.consumeProcessOutput(sout1, serr1)
p1.waitFor()
serr1.eachLine { println it }
def lines = sout1.readLines()
if (lines.size() > 0) {
println lines[0]
lines[1..-1].takeWhile { !it.startsWith("\"") }.each { println it }
}
println()
count++
}
if (!begin && line.trim().toUpperCase().startsWith("PID")) {
begin = true
}
}