@ExtensionMethod
注解简化从 Map<String, Object>
中获取 Integer
和 Long
类型的值
在 Java 编程中,我们经常需要从 Map<String, Object>
中获取特定类型的值。然而,由于 Map 的值是以 Object
类型存储的,因此在获取特定类型的值时往往需要进行类型转换。这种转换过程可能会导致代码冗长且容易出错。本文将介绍如何使用 Lombok 的 @ExtensionMethod
注解来简化这一过程,并提供一个实用的工具类来帮助我们处理从 Map<String, Object>
中获取 Integer
和 Long
类型的值。 @ExtensionMethod
注解?@ExtensionMethod
是 Lombok 提供的一个注解,它允许我们为现有的类添加扩展方法。通过使用这个注解,我们可以在不修改原类的情况下,为其添加新的方法。这样可以使我们的代码更加简洁,并提高可读性和可维护性。
首先,我们创建一个 ObjectConverter
工具类,提供将各种类型对象转换为 Integer
和 Long
类型的方法:
package com.zibo.common.converter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
/**
* 对象转换器
* -
* 提供将各种类型对象转换为 Integer 和 Long 类型的方法
*
* @author zibo
* @date 2024/8/25 10:50
* @slogan 慢慢学,不要停。
*/
public class ObjectConverter {
// 私有构造函数,防止实例化
private ObjectConverter() {
}
// 使用 Map 存储不同类型的 Integer 转换逻辑
private static final Map<Class<?>, Function<Object, Optional<Integer>>> integerConverters = new HashMap<>();
// 使用 Map 存储不同类型的 Long 转换逻辑
private static final Map<Class<?>, Function<Object, Optional<Long>>> longConverters = new HashMap<>();
static {
// String 转换为 Integer 的逻辑
integerConverters.put(String.class, source -> {
try {
return Optional.of(Integer.parseInt((String) source));
} catch (NumberFormatException e) {
// 当字符串无法解析为整数时,返回 Optional.empty()
return Optional.empty();
}
});
// BigInteger 转换为 Integer 的逻辑
integerConverters.put(BigInteger.class, source -> {
BigInteger bigInteger = (BigInteger) source;
if (bigInteger.bitLength() <= 31) {
// 检查 BigInteger 是否在 Integer 范围内
return Optional.of(bigInteger.intValue());
} else {
// 超出范围则返回 Optional.empty()
return Optional.empty();
}
});
// BigDecimal 转换为 Integer 的逻辑
integerConverters.put(BigDecimal.class, source -> {
BigDecimal bigDecimal = (BigDecimal) source;
if (bigDecimal.compareTo(BigDecimal.valueOf(Integer.MAX_VALUE)) <= 0 &&
bigDecimal.compareTo(BigDecimal.valueOf(Integer.MIN_VALUE)) >= 0) {
// 检查 BigDecimal 是否在 Integer 范围内
return Optional.of(bigDecimal.intValue());
} else {
// 超出范围则返回 Optional.empty()
return Optional.empty();
}
});
// Long 转换为 Integer 的逻辑
integerConverters.put(Long.class, source -> {
Long longValue = (Long) source;
if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
// 检查 Long 是否在 Integer 范围内
return Optional.of(longValue.intValue());
} else {
// 超出范围则返回 Optional.empty()
return Optional.empty();
}
});
// Integer 类型不需要转换,直接返回
integerConverters.put(Integer.class, source -> Optional.of((Integer) source));
// 通用 Number 类型转换为 Integer 的逻辑
integerConverters.put(Number.class, source -> Optional.of(((Number) source).intValue()));
// String 转换为 Long 的逻辑
longConverters.put(String.class, source -> {
try {
return Optional.of(Long.parseLong((String) source));
} catch (NumberFormatException e) {
// 当字符串无法解析为长整数时,返回 Optional.empty()
return Optional.empty();
}
});
// BigInteger 转换为 Long 的逻辑
longConverters.put(BigInteger.class, source -> {
BigInteger bigInteger = (BigInteger) source;
if (bigInteger.bitLength() <= 63) {
// 检查 BigInteger 是否在 Long 范围内
return Optional.of(bigInteger.longValue());
} else {
// 超出范围则返回 Optional.empty()
return Optional.empty();
}
});
// BigDecimal 转换为 Long 的逻辑
longConverters.put(BigDecimal.class, source -> {
BigDecimal bigDecimal = (BigDecimal) source;
if (bigDecimal.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) <= 0 &&
bigDecimal.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) >= 0) {
// 检查 BigDecimal 是否在 Long 范围内
return Optional.of(bigDecimal.longValue());
} else {
// 超出范围则返回 Optional.empty()
return Optional.empty();
}
});
// Long 类型不需要转换,直接返回
longConverters.put(Long.class, source -> Optional.of((Long) source));
// Integer 转换为 Long 的逻辑
longConverters.put(Integer.class, source -> Optional.of(((Integer) source).longValue()));
// 通用 Number 类型转换为 Long 的逻辑
longConverters.put(Number.class, source -> Optional.of(((Number) source).longValue()));
}
/**
* 将对象转换为 Integer 类型
*
* @param source 源对象
* @return 转换后的 Integer 类型的 Optional 包装
*/
public static Optional<Integer> toInteger(Object source) {
if (source == null) {
// 如果源对象为 null,返回 Optional.empty()
return Optional.empty();
}
// 从 Map 中获取对应类型的转换函数
Function<Object, Optional<Integer>> converter = integerConverters.get(source.getClass());
if (converter != null) {
// 如果找到转换函数,执行转换
return converter.apply(source);
}
// 如果没有对应的转换逻辑,返回 Optional.empty()
return Optional.empty();
}
/**
* 将对象转换为 Long 类型
*
* @param source 源对象
* @return 转换后的 Long 类型的 Optional 包装
*/
public static Optional<Long> toLong(Object source) {
if (source == null) {
// 如果源对象为 null,返回 Optional.empty()
return Optional.empty();
}
// 从 Map 中获取对应类型的转换函数
Function<Object, Optional<Long>> converter = longConverters.get(source.getClass());
if (converter != null) {
// 如果找到转换函数,执行转换
return converter.apply(source);
}
// 如果没有对应的转换逻辑,返回 Optional.empty()
return Optional.empty();
}
}
接下来,我们创建一个 MyMapUtils
工具类,使用 ObjectConverter
中的方法来简化从 Map<String, Object>
中获取 Integer
和 Long
类型的值:
package com.zibo.common.util;
import com.zibo.common.converter.ObjectConverter;
import java.util.Map;
/**
* map 工具类
* -
* 提供从 Map<String, Object> 中获取 Integer 和 Long 类型的值的方法
*
* @author zibo
* @date 2024/8/25 上午11:51
* @slogan 慢慢学,不要停。
*/
public class MyMapUtils {
private MyMapUtils() {
}
/**
* 从 Map<String, Object> 中获取 Integer 类型的值
*
* @param map Map<String, Object> 对象
* @param key 键
* @return 值
*/
public static Integer getInteger(Map<String, Object> map, String key) {
return ObjectConverter.toInteger(map.get(key)).orElse(null);
}
/**
* 从 Map<String, Object> 中获取 Long 类型的值
*
* @param map Map<String, Object> 对象
* @param key 键
* @return 值
*/
public static Long getLong(Map<String, Object> map, String key) {
return ObjectConverter.toLong(map.get(key)).orElse(null);
}
}
@ExtensionMethod
简化代码在主类中,我们使用 @ExtensionMethod
注解,将 MyMapUtils
中的方法作为 Map<String, Object>
的扩展方法使用:
package com.zibo;
import com.zibo.common.util.MyMapUtils;
import java.util.HashMap;
import java.util.Map;
import lombok.experimental.ExtensionMethod;
@ExtensionMethod(MyMapUtils.class)
public class Main {
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("key1", 123);
map.put("key2", "456");
map.put("key3", "sfdsa");
map.put("key4", true);
System.out.println(map.getInteger("key1"));
System.out.println(map.getInteger("key2"));
System.out.println(map.getInteger("key3"));
System.out.println(map.getInteger("key4"));
System.out.println(map.getInteger("key5"));
System.out.println();
System.out.println(map.getLong("key1"));
System.out.println(map.getLong("key2"));
System.out.println(map.getLong("key3"));
System.out.println(map.getLong("key4"));
System.out.println(map.getLong("key5"));
}
}
通过使用 Lombok 的 @ExtensionMethod
注解,我们可以为现有类添加扩展方法,从而简化代码并提高可读性。在本文中,我们创建了一个实用的工具类 MyMapUtils
,并使用 @ExtensionMethod
将其方法作为 Map<String, Object>
的扩展方法使用,使得从 Map 中获取特定类型的值变得更加简单和直观。这种方法不仅减少了代码冗余,还提高了代码的可维护性,是我们在日常开发中可以考虑采用的一种技巧。