Java 中集合的自定义运算符

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

运算符重载以多种语言提供。 Java 的运算符重载非常有限,因为它支持 String 类型的 + 运算符。

我们可以利用其他语言支持运算符的不同方式,但我们能否在 Java 中使用 Java 已经使用的约定来实现?

获取、设置和放置操作

集合运算符重载的一个常见示例是使用数组表示法 a[b] 来访问集合本身。获取它时很简单,因为 List 和 Map 都有一个 get 方法,这与 JavaBean getXxx() 命名约定一致。


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

当谈到基于索引或键设置值时,我们有来自 JavaBeans 的 List.set()、Map.put() 和 setXxx()。我们可以通过三种方式来解决这个问题。

  1. 为 Map 添加一个 set 方法。
  2. 使用查找 set 或 put 方法的约定,如果两者都有则抱怨。
  3. 默认为 set() 但添加一个注解将其覆盖到 put()。
  4. 我们为所有集合添加了一个新的特殊方法来进行设置。

最简单的演示选项是编译器选择 set 或 put,尽管这不太可能是最佳选项。


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

添加操作

添加操作更有趣,因为它可以组合使用。


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

最后一个示例存在开发人员可能在不知不觉中对线程安全集合执行不安全操作的问题。如果这被映射到...


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

这可以通过底层 List 实现线程安全。

同样对于地图,您可以调用计算


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

转换为


 List<String> text = ...

String s = text[2]; // text.get(2);

Map<String, MyType> map = ...

MyType mt = map["Hello"]; // map.get("Hello")

MyType mt = ...

String xxx = ...

String s = mt[xxx]; // mt.getXxx();

结论

只需对现有代码进行很小的更改,就可以添加对对象类型的运算符支持。您可以使用现有约定,但您可能会发现在某些情况下需要使用注释来更明确地控制其工作方式。