集合的处理:JDK和Guava孰强孰弱?

01 引言

在日常开发中,集合的操作是无法避开的。对于集合的操作,你是在JDK的流式处理还是Guava处理呢?

JDK8以前对于集合的处理,基本上只能遍历处理。而Guava对于集合操作的封装,简直不要太爽,备受广发开发者好评。而JDK8以后,流式处理简化了集合的操作,慢慢的吸引了一批开发者成为忠粉。

但是单独对于集合的处理,JDKGuava孰强孰弱?

02 集合处理需求

数据准备:

@Data
@AllArgsConstructor
public class User {
    Integer id;
    String name;
    int age;
}

// 集合
List<User> list = new ArrayList<>();
list.add(new User(1, "name1", 4));
list.add(new User(2, "name2", 8));
list.add(new User(3, "name3", 4));
list.add(new User(4, "name4", 6));
list.add(new User(5, "name5", 8));

处理任务:

  • list转Map
  • 通过年龄属性分组
  • List分片
  • Map集合的处理

03 流式处理对比Guava

先回顾一下传统的集合处理方法,无疑就是遍历。

for (User user : list) {
    // 业务处理        
}

传统的处理方式不是不好,反而更加通用。但是相比一些特定的处理,传统的方式相对而言麻烦一下。

Guava的Maven依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>33.4.8-jre</version>
</dependency>

3.1 List转Map

业务开发中,我们查询一个列表数据,需要填充数据的某个属性时,就是需要先查出集合中数据对应在另外一个表的属性,然后转成以idkey, 当前对象为value转成Map。遍历填充的时候,就可以直接通过Map获取即可。

有没有人知己在遍历的时候,直接通过查询的数据库的方式,填充数据的?这种方式是不可取的,当数量大时,这种处理方式就会暴漏出弊端。有多少数据量,就有多少次IO的处理。

对于案例数据,我们就将list转化成以idkeyuservalue的Map。

// 传统的写法
Map<Integer, User> map1 = new HashMap<>();
for (User user : list) {
    map1.put(user.getId(), user);       
}

// JDK8流式处理
Map<Integer, User> collect = list.stream()
    .collect(Collectors.toMap(User::getId, Function.identity()));

// Guava处理
ImmutableMap<Integer, User> immutableMap = Maps.uniqueIndex(list, User::getId);

从案例代码上来看,JDK8Guava都是一行代码完成了List到Map的转化,代码确实精简不少。JDK8Guava处理的结果集是不可变集合,无法再次像集合中添加元素,而传统的写法,却不受限制。

我们技术上难度

我们假设id有重复的,增加重复的数据:

list.add(new User(5, "name6", 9));

此时,流式处理和Guava的写法,全部崩溃,大致的报错都是因为key重复导致的。

JDK报错:

Guava报错:

然而JDK的流式处理,提供另外一个重载方法课解决此问题:

Map<Integer,User> userMap4 = list.stream()
    .collect(Collectors.toMap(User::getId, Function.identity(),(value1,value2)->value2));

后面的参数指定了取值,如果Key重复,则选用第二个参数。但从这一点上JDK8的流式处理略胜一筹。

3.2 通过年龄属性分组

通过属性分组,是另外的一种List转Map,就是当key重复的时候,将value只通过List集合收集起来。

// JKD8 流式处理
Map<Integer, List<User>> collect1 = list.stream().collect(Collectors.groupingBy(User::getAge));

// Guava 处理
ImmutableListMultimap<Integer, User> indexed = Multimaps.index(list, User::getAge);

但看这种处理方式,几乎没有什么区别,都非常简洁。

3.3 List分片

List分片在处理海量数据的时候需要用到,通过分片,将分片数据交给不同的算子,以提高处理速度。分而治之的思想就体现在这里。

List的分片JDK并没有提供现成的方法,可以说Guava完胜。但是我们依然可以自行实现分片的功能。

// 为了方便,我们使用整型数据
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8);

// Guava 的处理
List<List<Integer>> partition = Lists.partition(list, 3);

我们可以看到:

将原集合分成了三组。

JDK 自行实现

List<List<Integer>> partition2 = myListPartition(list, 3);
System.out.println(partition2);

private List<List<Integer>> myListPartition(List<Integer> list, int size) {
    List<List<Integer>> partition2 = new ArrayList<>();
    // 总长度
    int len = list.size();
    // 每一组的长度
    int groupSize = (int) Math.ceil((double) len / size);
    for (int i = 0; i < groupSize; i++) {
        int index = i * size;
        int end = Math.min(index + size, len);
        partition2.add(list.subList(index, end));
    }
    return partition2;
}

3.4 Map集合的处理

Map集合的处理JDK的流式处理,可能就会略显冗长,但是更灵活。

// 数据准备
Map<Integer, User> maps = new HashMap<>();
maps.put(1, new User(1, "name1", 4));
maps.put(2, new User(2, "name2", 6));
maps.put(3, new User(3, "name3", 8));
maps.put(4, new User(4, "name4", 6));

修改Map集合的Value为name属性

// JDK 处理
Map<Integer, String> collect = maps.entrySet().stream()
    .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getName()));

// Guava 处理
Map<Integer, String> strMap = Maps.transformValues(maps, User::getName);
// 或者 
Map<Integer, Integer> strMap = Maps.transformEntries(maps, (k, v) ->v.getName()));

处理的时候发现一个问题,就是Guava的处理只能针对value,而JDK的处理既可以处理Key,也可以处理Value

04 小结

对于工具的使用熟能生巧,并不是一定要分出哪个一定好,哪个一定坏,只不过是使用的场景不同而已。重要的事,你用了什么不重要,重要的事你能把问题解决了。

你们更习惯使用哪种方式呢?评论区留言。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智_永无止境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值