本文主要介绍Guava中几种处理字符串和Map的方法,包括Joiner(连接)、FluentIterable(过滤、转换集合)和Splitter(分割)。本文基于Java 8进行测试,Guava 版本为:

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

Joiner

我们来看看下面经常遇见的一个案例:定义包含如下元素的一个列表,请按照英文逗号分割,并过滤掉值为null的元素。

"a", null, "b", "g", "8", "9"

用JDK中的方法做的实现方案如下:

    @Test
public void joinerListByJdkTest() {
List<String> lists = Lists.newArrayList("a", null, "b", "g", "8", "9");
StringBuilder sb = new StringBuilder();
for (Object item : lists) {
if (item != null) {
sb.append(item)
.append(DELIMITER);
}
}
LOGGER.info(sb.substring(0, sb.length() - DELIMITER.length()));
}

执行结果:a,b,g,8,9。

是不是很简单,但是繁琐?例如,在for循环执行结束之后必须修正字符串末尾的分隔符:sb.substring(0, sb.length() - DELIMITER.length());Guava版本呢?

    @Test
public void joinerListByGuavaTest() {
List<String> lists = Lists.newArrayList("a", null, "b", "g", "8", "9");
String result = Joiner.on(DELIMITER).skipNulls().join(lists);
LOGGER.info(result);
}

我们不再考虑更多的细节,并且很有语义的告诉代码的阅读者用什么分隔符分隔,需要过滤null值再join。

关于Map对象的连接,Guava提供了withKeyValueSeparator用于指定键值对直接的分隔符。

    /**
* joiner withKeyValueSeparator(String keyValueSeparator) map连接器,keyValueSeparator为key和value之间的分隔符
* <p>
* 结果:
* 1:哈哈,2:压压
*/
@Test
public void withMapTest() {
Map<Integer, String> maps = Maps.newHashMap();
maps.put(1, "哈哈");
maps.put(2, "压压");
String result = Joiner.on(DELIMITER).withKeyValueSeparator(":").join(maps);
System.out.println(result);
}

FluentIterable

转换(transform)集合类型,transform接收Function接口,一般在方法中采用new接口实现回调方法apply的方式。

FluentIterable 是guava集合类中常用的一个类,主要用于过滤、转换集合中的数据;它是一个抽象类,实现了Iterable接口,大多数方法都返回FluentIterable对象,这也是guava的思想之一。下面主要针对filter 和transform方法进行演示。filter方法要接收Predicate接口,transform接收Function接口。

Filter的应用实例:

    /**
* 过滤出年龄大于20岁的学生
* <p>
* 这里有一个潜在的坑,在高版本(21.0++)的guava中Predicate接口继承了java 8中的java.util.function.Predicate
*
* @param students
*/
public static void filterStudents(List<Student> students) {
FluentIterable<Student> filter = FluentIterable.from(students).filter(
new Predicate<Student>() {
@Override
public boolean apply(Student student) {
return Integer.valueOf(student.getAge()) > 20;
}
});
for (Student student : filter) {
System.out.println(student);
}
}

transform三种类型的应用:

    private void myTest(List<Student> students) {
FluentIterable<String> transform = (FluentIterable<String>) FluentIterable.from(students).transform(
new Function<Student, String>() {
@Override
public String apply(Student user) {
// 以分隔符#分隔姓名和年龄
return Joiner.on("#").join(user.getName(), user.getAge());
}
});
for (String user : transform) {
System.out.println(user);
}
} /**
* 返回格式化后的列表
*/
private void myTestList(List<Student> students) {
// 直接返回 List 类型对象
List<String> transform = FluentIterable.from(students).transform(
new Function<Student, String>() {
@Override
public String apply(Student user) {
return Joiner.on("=").join(user.getName(), user.getAge());
}
}).toList();
System.out.println(transform);
} /**
* 定制特殊格式,并返回合并后的字符串
* 这里有一个潜在的坑,在版本 18.0才可以使用 .join(Joiner.on("、"))
* @param students
*/
private void givenFormater(List<Student> students) {
String result = FluentIterable.from(students).transform(new Function<Student, String>() {
@Override
public String apply(Student user) {
// 通过特殊格式定制字符串
return user.getName() + "(" + user.getAge() + ")";
}
// 指定各个字符串之间的分隔符
}).join(Joiner.on("、")); System.out.println(result);
}
@Test
public void guavaStudy() {
List<Student> students = new ArrayList<>();
Student student = new Student();
student.setName("Lucy");
student.setAge("19");
students.add(student);
students.add(new Student("Wiener", "32", "河南商丘"));
students.add(new Student("East7", "21")); myTest(students);
LOGGER.info("----- givenFormater ------");
givenFormater(students);
myTestList(students);
LOGGER.info("----- filterStudents ------");
filterStudents(students);
}

函数givenFormater比较特殊,其执行结果如下:

Lucy(19)、Wiener(32)、East7(21)

可以看到,其定制结果集格式的功能非常强悍。

Splitter

Splitter可以对字符串进行分割,其分割的方式有两种——按字符/字符串分割和按正则进行分割,下面分析按字符分隔。

   /**
* on 按照指定分隔符分隔字符串
* 结果:[ 河南商丘, 767, 32, , 哈哈 ]
*/
@Test
public void splitterListTest() {
String test = " 河南商丘,767,32,,哈哈 ";
List<String> lists = Splitter.on(DELIMITER).splitToList(test);
System.out.println(lists);
}
/**
* trimResults 拆分并且去除元素前后空格
* <p>
* 结果:[河南商丘, 767, 32, , 哈哈]
*/
@Test
public void trimResultListTest() {
String test = " 河南商丘,767,32,,哈哈 ";
List<String> lists = Splitter.on(DELIMITER).trimResults().splitToList(test);
System.out.println(lists);
} /**
* omitEmptyStrings 去除拆分后的、空的字符串
* <p>
* 结果:[河南商丘, 767, 32, 哈哈]
*/
@Test
public void omitEmptyStringsTest() {
String test = " 河南商丘,767,32,,哈哈 ";
List<String> lists = Splitter.on(DELIMITER).omitEmptyStrings().trimResults().splitToList(test);
System.out.println(lists);
}

Reference

https://www.cnblogs.com/whitewolf/p/4214749.html

<

Guava中的常见集合操作用法的更多相关文章

  1. JavaScript常见集合操作

    JavaScript常见集合操作 集合的遍历 FOR循环(效率最高) 优点:JavaScript最普遍的for循环,执行效率最高 缺点:无法遍历对象 for(let i=0;i<array.le ...

  2. 强大的Guava中的新集合类型: Multiset, Multimap, BiMap, Table, ClassToInstanceMap, RangeSet, RangeMap等

    一 Multiset /** * 新类型集合: Multiset: Multiset就是可以保存多个相同的对象,并且无序 * 占据了List和Set之间的一个灰色地带 * 其他实现: TreeMult ...

  3. Python中的SET集合操作

    python的set和其他语言类似, 是一个无序不重复元素集, 基本功能包括关系测试和消除重复元素. 集合对象还支持union(联合), intersection(交), difference(差)和 ...

  4. 认识python中的set集合及其用法

    python中,集合(set)是一个无序排列,可哈希, 支持集合关系测试,不支持索引和切片操作,没有特定语法格式, 只能通过工厂函数创建.集合里不会出现两个相同的元素, 所以集合常用来对字符串或元组或 ...

  5. Python中字典和集合的用法

    本人开始学习python 希望能够慢慢的记录下去 写下来只是为了害怕自己忘记. python中的字典和其他语言一样 也是key-value的形式  利用空间换时间 可以进行快速的查找 key 是唯一的 ...

  6. Guava中Predicate的常见用法

    Guava中Predicate的常见用法 1.  Predicate基本用法 guava提供了许多利用Functions和Predicates来操作Collections的工具,一般在 Iterabl ...

  7. Guava库介绍之集合(Collection)相关的API

    作者:Jack47 转载请保留作者和原文出处 欢迎关注我的微信公众账号程序员杰克,两边的文章会同步,也可以添加我的RSS订阅源. 本文是我写的Google开源的Java编程库Guava系列之一,主要介 ...

  8. java中的集合操作类(未完待续)

    申明: 实习生的肤浅理解,如发现有错误之处.还望大牛们多多指点 废话 事实上我写java的后台操作,我每次都会遇到一条语句:List<XXXXX> list = new ArrayList ...

  9. Linux中find常见用法

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  10. [转]Linux中find常见用法示例

    Linux中find常见用法示例[转]·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;find命令的参 ...

随机推荐

  1. C# TCP/IP通信,Socket通信例子

    1.服务端建立监听,等待客户端连接 class Program { static void Main(string[] args) { TcpListener listener = new TcpLi ...

  2. 添加xxx.so到环境变量里

    点击查看代码 libxxx.so 文件位于 /usr/local/lib 目录下,你可以按照以下步骤操作: 创建配置文件: echo "/usr/local/lib" | sudo ...

  3. 【MATLAB习题】工程测试时域、频域分析

    代码: classdef App_uoye < matlab.apps.AppBase % Properties that correspond to app components proper ...

  4. 【译】Visual Studio 中新的强大生产力特性

    有时候,生活中的小事才是最重要的.在最新版本的 Visual Studio 中,我们增加了一些功能和调整,目的是让您脸上带着微笑,让您更有效率.这里是其中的一些列表,如果您想要完整的列表,请查看发行说 ...

  5. delphi获取DOS命令行输出函数 运行CMD命令并获取结果

    procedure TForm1.Button4Click(Sender: TObject); var hReadPipe,hWritePipe:THandle; si:STARTUPINFO; ls ...

  6. Zotero设置

    1. 说明 Zotero 中文社区 | 百度网盘 使用 zotero 仅同步题录信息,使用其他云同步程序同步文献的附件,此处以坚果云为例进行演示,前期的坚果云同步设置参考文章:Zotero坚果云同步. ...

  7. MySQL-脏页的刷新机制

    MySQL内存结构-缓冲区 MySQL的缓冲区中有数据页,索引页,插入缓冲等等,这个角度是从页的功能来分类的.本小节从另一个视角关注这些页,如果从 是否被修改过(和磁盘不一致) 这个角度来区分这些页, ...

  8. FastAPI依赖注入:从基础概念到应用

    title: FastAPI依赖注入:从基础概念到应用 date: 2025/04/04 16:28:51 updated: 2025/04/04 16:28:51 author: cmdragon ...

  9. Mybatis三大执行器

    目录 1.执行器介绍 执行器的选择入口 设置执行器两种方式 全局配置(不建议) 局部设置(建议) 2.三个执行器区别 SimpleExecutor ReuseExecutor BatchExecuto ...

  10. 多线程的waiting与notify

    一.waiting()与notify() /* 进入到TimeWaiting(计时等待)有两种方式 1.使用sleep(long m)方法,在毫秒值结束之后,线程睡醒进入到Runnable/Block ...