腾飞工作室

groovy和Java混合编程之集合的使用

groovy 简化了 Java 语法,并且增加了一些集合的常用操作
Java8 中也提供了 stream 以满足复杂的集合操作需求
日常集合操作代码案例这里都有

创建

创建数组

1
String[] contents = { "tom", "jerry", "bill"};

创建list

  • java 语法
1
2
3
4
5
List<User> list = new ArrayList<User>(){{
add(new User("tom",18));
add(new User("bill",14));
add(new User("jerry",16));
}};
  • groovy 语法

集合与数组的转换

创建map

###

  • java 语法

  • groovy 语法

    def map=[:]   //空的map
    def map=["a":1 ,"b":2]
    

遍历

Java 遍历 list

groovy 遍历 list

Java 遍历 map

  • 方法一

    def map = ["a": 1, "b": 2]
    for (Map.Entry<String,Integer> entry : map) {
        println entry.key+"---"+entry.value
    }
    
  • 方法二

    只对 key 遍历
    for (String key : map.keySet()) {
        System.out.println(key + " = " + map.get(key));
    }
    
    只对 value 遍历
    for (String value : map.values()) {
        System.out.println("value = " + value);
    }
    
  • 方法三

    Iterator<Map.Entry<String, Integer>> entries = map.entrySet().iterator();
    while (entries.hasNext()) {
        Map.Entry<String, Integer> entry = entries.next();
        System.out.println(entry.key + " = " + entry.value);
    }
    
  • 方法四

    考虑实际场景如果你的value类型比较复杂你最好带着泛型
    map.forEach((String k,Integer v)->{
        System.out.println(k+" = "+v);
    });
    
    如果比较简单当然你可以把泛型去掉
    map.forEach((k,v)->{
        System.out.println(k+" = "+v);
    });
    
    如果仅仅是输出你还可以更简单
    map.forEach((k,v)-> System.out.println(k+" = "+v));
    

groovy 遍历 map

  • 方法一

    map.each { k, v ->
        println k + "---" + v
    }
    
  • 方法二:可以获取下标

    map.eachWithIndex { Map.Entry<String, Integer> entry, int i ->
        println entry.key + " = " + entry.value+ "---"+i
    }
    

筛选

去重

排序

集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
List<User> list = [
new User(name: "tom", age: 18),
new User(name: "bill", age: 18),
new User(name: "jerry", age: 16),
new User(name: "judy", age: 36)
]
//Java对集合的排序
Collections.sort(list,new Comparator<User>() {
//原则:
// x 中所有大于 y 的都返回正数,正序排列
// x 中所有小于 y 的都返回负数,倒序排列
// x 中所有等于 y 的都返回0,不排序
@Override
int compare(User x, User y) {
//正序排列
return x.age.compareTo(y.age)
return x.age-y.age
//降序
return y.age.compareTo(x.age)
return y.age-x.age
}
})
prinln "集合排序:"+list
//Java 对数组排序
User[] userArray =[
new User(name: "tom", age: 18),
new User(name: "bill", age: 18),
new User(name: "jerry", age: 16),
new User(name: "judy", age: 36)
]
Arrays.sort(userArray, new Comparator<User>() {
@Override
int compare(User o1, User o2) {
//正序
return o1.age.compareTo(o2.age)
//倒序
return o2.age.compareTo(o1.age)
}
})
println "数组排序:"+userArray
//Java8中可以使用 lambda 表达式来写
//升序
list.sort((o1, o2) -> o1.getAge().compareTo(o2.getAge())); //方法1
list.sort(Comparator.comparing(User::getAge));//方法2
Collections.sort(list, Comparator.comparing(User::getAge));//方法3
//倒序
list.sort((o1, o2) -> o2.getAge().compareTo(o1.getAge()));//方法1
list.sort(Comparator.comparing(User::getAge).reversed());//方法2
Collections.sort(list, Comparator.comparing(User::getAge).reversed());//方法3
//groovy 的闭包对集合和数组的排序可以如下简写
list.sort { x, y ->
//正序
return x.age.compareTo(y.age)
return x.age-y.age
return x.age <=> y.age
//倒序
return y.age.compareTo(x.age)
return y.age-x.age
return y.age <=> x.age
}
prinln "排序后:"+list
//groovy 打乱一个集合或者数组
Integer[] arr = [2, 4, 6, 1, 0]
def arr2 = arr.sort{
Math.random()
}
println arr2

分组

合并

多个 list 合并成一个

List<List<Integer>> list = [[1], [11,12], [21,22,23], [31,32,33], [41,42,43,44]]
List<Integer> result = list.stream()
                        .flatMap({ it.stream().map({it}) })
                        .collect(Collectors.toList());

或者
 List<Integer> result = list.stream()
            .flatMap(Collection::stream)
            .collect(Collectors.toList());

println list

输出结果:[1, 11, 12, 21, 22, 23, 31, 32, 33, 41, 42, 43, 44]

复杂的场景:多个异步执行结果的返回值合并到一起

CompletableFuture future1=CompletableFuture.supplyAsync({
    TimeUnit.SECONDS.sleep(1) //延迟一秒返回
    return [1,2,3]
});
CompletableFuture future2=CompletableFuture.supplyAsync({
    TimeUnit.SECONDS.sleep(5) //延迟五秒返回
    return [4,5,6,7,8,9]
});

List<Integer> collect= Stream.of(future1,future2)
        .flatMap({(it.join() as List<Integer>).stream().map({it}) })
        .collect(Collectors.toList());
println collect

五秒钟后输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9]

多个map的结果合并到一起

转换

list 转 map

一个list:提取一个属性作为key,其他的值作为value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Person {
Integer salary
String emailId
}
Person person1=new Person(salary:25000,emailId:"anamika@gmail.com")
Person person2=new Person(salary:23000,emailId:"sanjana@gmail.com")
Person person3=new Person(salary:26000,emailId:"khalid@gmail.com")
Person person4=new Person(salary:20000,emailId:"anjali@gmail.com")
Person person5=new Person(salary:22000,emailId:"aditya@gmail.com")
List<Person> persons=[person1,person2,person3,person4,person5]
//方法一
Map<String,Integer> result = persons.collectEntries{
[it.emailId,it.salary]
}
//方法二
Map<String,Integer> result = persons.collectEntries{
[(it.emailId):it.salary]
}
//输出结果
Output of result -> [anamika@gmail.com:25000, sanjana@gmail.com:23000, khalid@gmail.com:26000, anjali@gmail.com:20000, aditya@gmail.com:22000]

java8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
List<PhotoExcel> list = [
new PhotoExcel(bucket: "a", dir: "a/a"),
new PhotoExcel(bucket: "a", dir: "a/b"),
new PhotoExcel(bucket: "b", dir: "b/b"),
new PhotoExcel(bucket: "b", dir: "b/b"),
]
def map = list.stream().collect(
Collectors.groupingBy(new Function<PhotoExcel, String>() {
@Override
String apply(PhotoExcel photoExcel) {
return photoExcel.bucket
}
}, Collectors.mapping(Function.identity(), Collectors.toList())))
println JSON.toJSONString(map)
//输出:{"a":[{"bucket":"a","dir":"a/a"},{"bucket":"a","dir":"a/b"}],"b":[{"bucket":"b","dir":"b/b"},{"bucket":"b","dir":"b/b"}]}

两个长度相同的list:一个list作为key,另外一个list对应的下标值作为value

setUp:   
    String[]  arr1 = ["a", "b", "c"]
    Integer[] arr2 = [4, 5, 6]
想要的结果:[a:4, b:5, c:6]

方法1:最常规的做法在遍历一个集合的同时通过下标获取另一个
     Map<String,Integer> result=[:]
    arr1.eachWithIndex { String entry, int i ->
        result.put(entry,arr2[i])
    }

方法2: 先转换为二维数组再把二维数组转换为map,感觉比较玩的花哨
    def result = [arr1, arr2].transpose()  //先转换为:[["a",4],["b",5],["c",6]]
             .inject([:]) { entry, it ->entry + [(it[0]):(it[1])]}


方法3:和方法2思想一样,只是混合 Java8 的语法
    def result = [arr1, arr2].transpose()
            .stream().collect(Collectors.toMap({it[0]},{it[1]}))

map 转 list

转换内容格式

def a=[1,2,3].stream().map({it+"转成字符串格式"}).collect(Collectors.toList())
def b=[1,2,3].collect({ it+"转成字符串格式" })
println a
println b

合并

map合并

1
2
3
4
5
6
7
8
Map a=["a":1]
Map b=["b":2]
Map c=["a":3] //相同的 key 后面的会把前面的覆盖
a.putAll(b)
a.putAll(c)
println a

分页

java8

1
2
3
4
5
6
7
8
9
10
11
12
int pageSize=20; //每页多少条
List<GoodsDTO> goodsList =new ArrayList<>(); //要分页的数据
int page = (goodsList.size() + (pageSize - 1)) / pageSize; //分页
List<List<GoodsDTO>> goodsListPage = Stream.iterate(0, n -> n + 1)
.limit(page)
.parallel()
.map(currPage ->
goodsList.stream()
.skip(currPage * pageSize)
.limit(pageSize)
.collect(Collectors.toList())
).collect(Collectors.toList());

guava

1
2
3
int pageSize=20; //每页多少条
List<GoodsDTO> goodsList =new ArrayList<>(); //要分页的数据
List<List<GoodsDTO>> lists = Lists.partition(goodsList, pageSize);

本文出自 “腾飞工作室” 博客,请务必保留此出处:http://tfgzs.net/2017/06/26/groovy和Java混合编程之集合的使用/