JFunctional
Functional programming for Java. Enhanced switch or simple pattern matching supported. String Interpolation supported. Java Functional Interface that more simpler and easier to use. 提供更简单更好用的Java函数式编程接口、增强版switch(简单的模式匹配)、字符串插值
Install / Use
/learn @GG-A/JFunctionalREADME
📚JFunctional
提供更简单更好用的Java函数式编程接口 (Java Functional Interface that more simpler and easier to use);
增强版switch(简单的模式匹配)(Enhanced switch or simple pattern matching supported);
字符串插值(String Interpolation);
提供元组(tuple)类型支持;
兼容Java 8及Java 9+模块化系统;
🎉
🎉
🎉
此项目已经迁移至(New Project):https://github.com/io-fairy/functional
🎉
🎉
🎉
🛠️Environment(开发环境)
- JDK 9.0.4
- Apache maven 3.6.1
💿新集成方式(兼容Java 8及Java 9+)
Maven
<dependency>
<groupId>com.iofairy</groupId>
<artifactId>functional</artifactId>
<version>0.0.1</version>
</dependency>
Gradle
implementation 'com.iofairy:functional:0.0.1'
💿旧集成方式(兼容Java 8及Java 9+)
Maven
<dependency>
<groupId>com.github.GG-A</groupId>
<artifactId>JFunctional</artifactId>
<version>0.8.7</version>
</dependency>
Gradle
implementation 'com.github.GG-A:JFunctional:0.8.7'
🗺️使用指南(User Guide)
📘增强版switch(简单的模式匹配)
增强版switch不仅支持传统switch语句匹配的类型(byte, short, char, int, enum and String),还支持:
- 任意类型的匹配
- 对象类型匹配(替代 instanceof)
- 条件匹配(替代if语句)
匹配对象的值
用于匹配两个值或对象是否相等,注意静态导入(import static com.github.gg_a.pattern.Pattern.*;)
- 带返回值的匹配
import static com.github.gg_a.pattern.Pattern.*;
String s = "5";
// 带返回值
String result = match(s)
.when("1", v -> v + v)
.when("2", v -> v + "a")
.when(in("3", "4", "5", "6"), v -> v + " - abcd") // in方法用于一次匹配多个值
.orElse(v -> "no match");
/*
* it is equivalent to the code below.
* 上面代码等同于如下switch代码
*/
String switchResult;
switch (s) {
case "1":
switchResult = s + s;
break;
case "2":
switchResult = s + "a";
break;
case "3":
case "4":
case "5":
case "6":
switchResult = s + " - abcd";
break;
default:
switchResult = "no match";
}
- 不带返回值的匹配
import static com.github.gg_a.pattern.Pattern.*;
int i = 10;
// 返回值为null
Void nullValue = match(i)
.when(1,
/*
* if you want to match `when(V matchValue, V1<V> action)` not `when(V matchValue, R1<V, R> action)`,
* you need add `{ }`, see: void-compatible and value-compatible
*/
v -> { System.out.println("match value:" + v); }) // add {} to void-compatible. 添加 {} 表示lambda无返回值,解决方法调用歧义(Ambiguous)问题
.whenNext(10,
v -> System.out.println("match value:" + v + " whenNext continue..."))
.when(20,
v -> System.out.println("match value:" + v))
.orElse(
v -> System.out.println("--orElse--"));
/*
* output:
* match value:10 whenNext continue...
* --orElse--
*/
🔔️注意:Lambda表达式的void兼容块与值兼容块。
null值匹配
可以匹配null值,可以不用使用 if(xxx == null){...} else {...}来进行null值的判断。
🔔️建议将 null 值优先匹配, 这样如果变量为null,则不会再执行后续的分支语句,很大程度避免 NullPointerException的异常。
import static com.github.gg_a.pattern.Pattern.*;
String s = null;
String strResult1 = match(s)
// Avoid "Ambiguous method call", if you want to match `null` value, you need use `(String) null` or in(null)
.when((String) null, v -> "string null value")
.when("abcd", v -> "is not null")
.orElse(v -> "other value");
assertEquals("string null value", strResult1);
String strResult2 = match(s)
.when(in(null), v -> "contains null value")
.when("abcd", v -> "is not null")
.orElse(v -> "other value");
assertEquals("contains null value", strResult2);
String strResult3 = match(s)
.when(in("a", "b", null, "c"), v -> "contains null value")
.when("abcd", v -> "is not null")
.orElse(v -> "other value");
assertEquals("contains null value", strResult3);
String nullStr = null;
String result = match(nullStr, BOOLEAN) // specify a BOOLEAN mode
.when(null, v -> "match string null")
.when("abc".equals(nullStr), v -> "i less than 1")
.orElse(v -> "str value: " + nullStr);
assertEquals("match string null", result);
Tuple2<String, Integer> t2 = null;
String classMatch = match(t2, TYPE)
.when(Integer.class, v -> "integer class")
.when(null, v -> "value is null: " + v)
.when(Tuple2.class, v -> "tuple2 class")
.orElse(v -> "other class");
assertEquals("value is null: " + null, classMatch);
String res = match(null, VALUE)
.when(null, v -> "null value")
.orElse(v -> "other value");
assertEquals("null value", res);
按类型匹配(替代instanceof)
import static com.github.gg_a.pattern.Pattern.*;
Object o = Tuple.of("zs", 20);
// add `TYPE` to match Class<?>. 这里需要加个TYPE,表示按类型匹配。
Integer result = match(o, TYPE)
.when(Integer.class, v -> v + 10)
.when(Tuple2.class, v -> v.arity())
.when(String.class, v -> v.contains("abc") ? 20 : 30)
.orElse(v -> 40);
/*
* it is equivalent to the code below.
* 上面代码等同于如下instanceof代码
*/
Integer ifResult;
if (o instanceof Integer) {
ifResult = (Integer) o + 10;
} else if (o instanceof Tuple2) {
ifResult = ((Tuple2) o).arity();
} else if (o instanceof String) {
ifResult = ((String) o).contains("abc") ? 20 : 30;
} else {
ifResult = 40;
}
String匹配
import static com.github.gg_a.pattern.Pattern.*;
String str = "aBcdE123.$fGHIj";
// ignore case match
String matchRes1 = match(str, IGNORECASE)
.when((String) null, v -> "match null")
.when("abcd", v -> "match abcd")
.when("abcde123.$fGHIj", v -> "ignore case match")
.orElse(v -> "no match");
assertEquals("ignore case match", matchRes1);
// CONTAIN match
String matchRes2 = match(str, CONTAIN)
.when("abcd", v -> "abcd")
.when("E123", v -> "E123")
.orElse(v -> "no match");
assertEquals("E123", matchRes2);
// ignore case for contain
String matchRes3 = match(str, ICCONTAIN)
.when("abcd1", v -> "abcd1")
.when(in(null, "aaa", ".$fghi", "123"), v -> ".$fghi")
.orElse(v -> "no match");
assertEquals(".$fghi", matchRes3);
// PREFIX
String matchRes4 = match(str, PREFIX)
.when("abcd", v -> "abcd")
.when("aBcd", v -> "aBcd")
.orElse(v -> "no match");
assertEquals("aBcd", matchRes4);
// ignore case for suffix
String matchRes5 = match(str, ICSUFFIX)
.when("fghij", v -> "fGHIj")
.when("aBcd", v -> "aBcd")
.orElse(v -> "no match");
assertEquals("fGHIj", matchRes5);
按条件匹配(替代if语句)
import static com.github.gg_a.pattern.Pattern.*;
int i = 10;
String result = match(i)
.when(i == 0,
v -> "i is zero")
.when(i < 5 && i > 0,
v -> "i is between 0~5")
.when(i > 5,
v -> "i is greater than 5")
.orElse(v -> "i is equals to: " + v);
System.out.println("match result:" + result);
/*
* it is equivalent to the code below
* 上面代码等同于如下if代码
*/
String ifResult;
if (i == 0) {
ifResult = "i is zero";
} else if (i < 5 && i > 0) {
ifResult = "i is between 0~5";
} else if (i > 5) {
ifResult = "i is greater than 5";
} else {
ifResult = "i is equals to: " + i;
}
📘String Interpolator(字符串插值器)
能做什么
取代不够优雅、可读性差的+号拼接字符串的方式以及Java内置字符串插值器MessageFormat.format()和String.format()
- 使用Java内置
int id = 12345;
String name = "zhangsan";
float height = 180.5f;
// 使用 + 号拼接
String res1 = "id: " + id + " 名字:" + name + " 身高(cm): " + height;
System.out.println(res1);
// 使用 MessageFormat.format
String res2 = MessageFormat.format("id: {0} 名字:{1} 身高(cm): {2}", id, name, height);
System.out.println(res2);
// 使用 String.format
String res3 = String.format("id: %d 名字:%s 身高(cm): %.1f", id, name, height);
System.out.println(res3);
- 使用string interpolator(可读性强)
SI si = Tuple.of(id, name, height).alias("id", "name", "height").toSI();
String s = si.$("id: ${id} 名字:${name} 身高(cm): ${height}");
System.out.println(s);
字符串插值(参数少时)
SI si = Tuple.of("zs", 20, "tom", 190.5, 123456).alias("name", "age", "nickName", "height", "id").toSI();
String parse = si.$("${name}--${age}--${nickName}--${id}--${height}"); // result: zs--20--tom--123456--190.5
字符串插值(参数多时)
SI si = SI.init(" ip -> ", "127.0.0.1",
" db -> ", "testdb",
" port -> ", 3306,
" dbType -> ", "mysql",
" other_info -> ", Tuple.of("isCluster", true),
"description -> ", new Object());
String dbInfo = si.$("ip: ${ip}---port: ${port}---db: ${db}---otherInfo: ${other_info}");
default-value(设置默认值)
// use ": " (: + space) set default value
String source = "${NAME}--${NAME: tom}--${age: 20}--${ID1:}--${ ID1 }--${ID1: }--${id1}--" +
"${age::20}--${ID}--${ ID1: }--${ID: 123456}";
Tuple t1 = Tuple.of("zs", null).alias("NAME", "ID");
String parse = SI.of(t1).$(source);
System.out.println(parse); // output: zs--zs--20--${ID1:}--${ ID1 }----${id1}--${age::20}--null-- --null
${} metachar(元字符)
SI si = Tuple.of("zs", 123456).alias("NAME", "ID").t
Related Skills
openhue
351.2kControl Philips Hue lights and scenes via the OpenHue CLI.
sag
351.2kElevenLabs text-to-speech with mac-style say UX.
weather
351.2kGet current weather and forecasts via wttr.in or Open-Meteo
casdoor
13.3kAn open-source AI-first Identity and Access Management (IAM) /AI MCP & agent gateway and auth server with web UI supporting OpenClaw, MCP, OAuth, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, Face ID, Google Workspace, Azure AD
