Groovy
Groovy是一种运行在Java虚拟机上的脚本语言,语法相比java起来简单很多。而且完全支持Java语法,这个不知道是不是好事,写习惯groovy再去写java会不会很容易混淆?所有Java的库都可以在Groovy上使用,可以说跟Java是互通的。Groovy的就是一跑在jvm上的脚本语言嘛,Groovy的代码最后也要被编译成为jvm上的字节码。
一直都打算学一种脚本语言来写脚本和小程序的,本来是用python的,用了几天,一放松又用回Java了。Java虽然库比较熟悉,代码比较亲切,但是用来写脚本还是太繁琐了。接触都Groovy后,感觉就是它了,有脚本语言的语法和Java的库,对于会Java的人来说,学习Groovy几乎是零成本的!
官网:http://groovy.codehaus.org (二级域名…orz) 装Groovy前要先安装好Java环境。 Groovy的环境配置:
文档方面:英文的该有还是有的.中文的就比较稀少了. netbeans下有个Groovy插件挺好用的,在同一个项目里Groovy文件可以跟java文件混用
groovy没有强制分号 groovy也没像python那样的强制缩进.还是得用花括号,这个比较可惜。
Groovy 默认导入了下面这些包
java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*
「==」操作符,不再比较引用,如下面的的代码输出2个true
a = new String("wtf")
b = new String("wtf")
println a == b
println a.equals(b)
Output:true
true
正则表达式也有独立的操作符,正则表达式要用两个斜杠包围起来。 是否匹配
==~ 如 println "potatoe" ==~ /potatoe/
Output:true
匹配结果 =~
会返回一个相当于java.util.regex.Matcher的对象。
闭包(Closure)
用python的时候还没用过闭包,毕竟是没接触过的特性所以有股阻力,Lisp则是想学还没动手,所以学Groovy也算是我第一次接触闭包了。
闭包就像这样 s = {println it}
一个变量名 指向一个代码块 调用s(5)
就会打印出 5 官方帮助的例子是
square = { it * it}
println square(9)
Output:81
闭包也可以当成方法的参数去传递; 如 [ 1, 2, 3, 4 ].collect(square)
闭包在java成面就是groovy.util.Closure这个类,
所以可以这样传递还可以理解。 关于闭包的参数;
默认一个参数就是it,可以不用声明直接用便可。
多于一个参数可以用下面这种方式来指定参数列表 closure = {a,b,...n -> code}
closure(a,b,...n)
还可以匿名[ "yue" : "wu", "lane" : "burks", "sudha" : "saseethiaseeleethialeselan" ].each(
{
key, value -> println key + "=" + value
})
闭包匿名的时候可以省略括号
[ "yue" : "wu", "lane" : "burks", "sudha" : "saseethiaseeleethialeselan" ].each
{
key, value -> println key + "=" + value
}
还可以这样写
n = 5;
({
for(int i in 1..100)
println i*n
}).call()
闭包内部可以调用其外部的变量 这个如何实现的也很好奇啊 在官网上的例子还看过这么一个用法
def groovyImage = new GroovyImage();
def argAndClosure = ['-d':{groovyImage.srcDir = new File(it)},
'-q':{groovyImage.outputPattern = it},
'-p':{groovyImage.pattern = it},
'-h':{groovyImage.help()}];
闭包当成Map的Value,直接Map[key].call()果然很方便。
看了一天目前知道的差不多就这些,刚接触闭包,概念还待慢慢理解;Groovy其他的特点还待慢慢发掘。
Groovy的效率
最后再看看Groovy的效率如何,分别在Java、Python、Groovy上写了个生成素数表的方法,代码几乎一致。 Java:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.dou.euler;
import java.util.ArrayList;
/**
*
* @author DouO
*/
public class Prime {
public static ArrayList<Long> primes = new ArrayList<Long>(100);
public static void buildPrimeTable(int n){
primes.add(2L);
primes.add(3L);
int k = 2;
long s = 5;
for (int i = 0; i < n-2; i++) {
int j = 0;
int q = (int) Math.ceil(Math.sqrt(s));;
while (j < i ) {
if (primes.get(j)<=q&&s % primes.get(j) == 0) {
s+=k;
k = (k+k)%6;
q = (int) Math.ceil(Math.sqrt(s));
j = 0;
} else {
j++;
}
}
j = 0;
primes.add(s);
s+=k;
k = (k+k)%6;
q = (int) Math.ceil(Math.sqrt(s));
}
}
public static void main(String[] args) {
long t = System.currentTimeMillis();
buildPrimeTable(10001);
System.out.println(System.currentTimeMillis() - t);
System.out.println(primes.get(10000));
}
}
Python:
import math
import time
primes = []
def buildTable(n):
# if(len(primes)<=0):
# primes.append(2)
# sindex = 1;
# else:
# sindex = len(primes+1);
primes.append(2)
primes.append(3)
s = 5
k = 2
for i in range(0,n):
j=0
q = int(math.sqrt(s)+0.5)
while(j<i):
if(primes[j]<=q and s%primes[j]==0):
s+=k
k=(k+k)%6
q = int(math.sqrt(s)+0.5)
j=0
else:
j+=1
primes.append(s)
s+=k
k=(k+k)%6
q = int(math.sqrt(s)+0.5)
time.clock()
buildTable(10000)
print primes[10000]
print time.clock()
Groovy:
primes = []
def buildPrimeTable(n){
primes.add(2)
primes.add(3)
s = 5
k = 2
for(i in 0..n-2){
j = 0
q = (int) Math.ceil(Math.sqrt(s))
while(j<i){
if(primes[j]<=q && s%primes[j]==0){
s+=k
k=(k+k)%6
q = (int) Math.ceil(Math.sqrt(s))
j = 0
}else{
j++;
}
}
primes.add(s)
s+=k
k = (k+k)%6
q = (int) Math.ceil(Math.sqrt(s))
}
}
t = System.currentTimeMillis()
buildPrimeTable(10000)
println System.currentTimeMillis() - t
println primes[10000]
以生成前10000位素数为例,结果如下: Java:718ms,表现不错。 Python:8833ms,8秒,java的10倍,也可能是我代码写的不好。 Groovy:77484ms,没错,你没看错是5位数,77秒!几乎是java版的110倍。天啊,这也忒慢了吧,是不是我触犯了什么禁忌啊,很可能出现在列表结构上面,下次再弄清楚啦。