一.JDK8 的增强
1.jdk8 增强与新特性
Java 8 引入了许多新的语言特性和 API 改进,以下是其中一些主要的特性:
- Lambda 表达式: Lambda 表达式是一种更简洁的语法,用于表示一个匿名函数。它使得在集合操作、事件处理等场景下代码更具可读性和简洁性。
- 函数式接口: Java 8 引入了函数式接口的概念,这是只包含一个抽象方法的接口。Lambda 表达式可以与函数式接口一起使用。
- 方法引用: 方法引用允许你直接引用现有的方法或构造函数,从而使代码更加简洁。
- 默认方法和静态方法: 接口现在可以包含默认方法和静态方法的实现。这使得在接口中添加新的方法时,不会破坏已有的实现。
- Stream API: Stream API 提供了一种更便捷的方式来处理集合数据。它支持函数式编程风格,可以用于过滤、映射、归约等操作。
- 新的日期和时间 API: Java 8 引入了
java.time
包,提供了全新的日期和时间 API,解决了旧的Date
和Calendar
类存在的问题。 - Optional 类:
Optional
是一个容器类,用于表示一个值可能存在,也可能不存在的情况,从而减少空指针异常的发生。 - Nashorn 引擎: Nashorn 是一个新的轻量级、高性能的 JavaScript 引擎,用于在 Java 程序中执行 JavaScript 代码。
- 新的重复注解和类型注解: 如前所述,Java 8 引入了对多重注解的支持,以及更丰富的类型注解。
- PermGen 空间被移除: Java 8 中,永久代(PermGen)被元空间(Metaspace)所取代,用于存放类的元数据。
2.Stream 的组成与特点
Stream
(流)是一个来自数据源的元素队列并支持聚合操作:
- 元素是特定类型的对象,形成一个队列。
Java
中的Stream
并不会向集合那样存储和管理元素,而是按需计算 - 数据源流的来源可以是集合
Collection
、数组Array
、I/O channel
, 产生器generator
等 - 聚合操作类似
SQL
语句一样的操作, 比如filter
,map
,reduce
,find
,match
,sorted
等
和以前的Collection
操作不同, Stream 操作还有两个基础的特征:
Pipelining
: 中间操作都会返回流对象本身。这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。这样做可以对操作进行优化, 比如延迟执行(laziness evaluation
)和短路(short-circuiting
)内部迭代
:以前对集合遍历都是通过Iterator
或者For-Each
的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。Stream
提供了内部迭代的方式, 通过访问者模式 (Visitor
)实现。
和迭代器又不同的是,Stream
可以并行化操作,迭代器只能命令式地、串行化操作。顾名思义,当使用串行方式去遍历时,每个 item
读完后再读下一个 item。而使用并行去遍历时,数据会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。
3.Stream 底层原理
示例代码:
public class Java8_01_Source_Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Red");
list.add("Green");
list.add("Blue");
long lengthyColors = list.stream().filter(c -> c.length() > 3).count();
System.out.println(lengthyColors);
}
}
javap -c -p Java8_01_Source_Main 查看class文件
> javap -c -p Java8_01_Source_Main
警告: 二进制文件Java8_01_Source_Main包含com.xiaofei.antjava8.源码.Java8_01_Source_Main
Compiled from "Java8_01_Source_Main.java"
public class com.xiaofei.antjava8.源码.Java8_01_Source_Main {
public com.xiaofei.antjava8.源码.Java8_01_Source_Main();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: ldc #4 // String Red
11: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
16: pop
17: aload_1
18: ldc #6 // String Green
20: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
25: pop
26: aload_1
27: ldc #7 // String Blue
29: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
34: pop
35: aload_1
36: invokeinterface #8, 1 // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
41: invokedynamic #9, 0 // InvokeDynamic #0:test:()Ljava/util/function/Predicate;
46: invokeinterface #10, 2 // InterfaceMethod java/util/stream/Stream.filter:(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;
51: invokeinterface #11, 1 // InterfaceMethod java/util/stream/Stream.count:()J
56: lstore_2
57: getstatic #12 // Field java/lang/System.out:Ljava/io/PrintStream;
60: lload_2
61: invokevirtual #13 // Method java/io/PrintStream.println:(J)V
64: return
private static boolean lambda$main$0(java.lang.String); // c -> c.length() > 3
Code:
0: aload_0
1: invokevirtual #14 // Method java/lang/String.length:()I
4: iconst_3
5: if_icmple 12
8: iconst_1
9: goto 13
12: iconst_0
13: ireturn
}
分析结论:
通过字节码可以看到 invokedynamic
指令以某种方式负责创建 Predicate 实例。
此方法以 字符串 作为输入,然后执行以下步骤:
- 计算输入长度(invokevirtual on length)
- 将长度与常量 3 进行比较(if_icmple 和 iconst_3)
- 如果长度小于或等于 3,则返回 false
Java 7 中之前,JVM 只是有四个方法调用类型:
- invokevirtual 调用正常类方法,
- invokestatic 调用静态方法,
- invokeinterface 调用接口的方法,
- invokespecial 调用构造函数或私有方法。
对于 lambda 表达式,Java 不是在编译时创建匿名内部类,而是在运行时通过调用动态创建它们
4.回调函数
#回调函数的写法 有套路的
#消息确认成功回调函数
ConfirmCallback ackCallback (deliveryTag,multiple)->{
}:
#消息确认失败回调函数
ConfirmCallback nackCallback (deliveryTag,multiple)->(
#准备消息的监听器监听哪些消息成功了哪些消息失败了
#异步通知
channel..addConfirmListener(ackCallback,nackCallback);
5.flatMap
public static void main(String[] args) {
List<Integer> lista = new ArrayList<>();
lista.add(1);
lista.add(3);
List<Integer> listb = new ArrayList<>();
listb.add(2);
listb.add(4);
List<List<Integer>> listc = new ArrayList<>();
listc.add(lista);
listc.add(listb);
System.out.println(listc);
List<Integer> listd = listc.stream().flatMap(ele -> ele.stream()).collect(Collectors.toList());
System.out.println(listd);
}
Map<String,List<Object>>使用java8转为 List<Object>
public static void main(String[] args) {
Map<String, List<Integer>> map = new HashMap<>();
map.put("1", Arrays.asList(1, 2, 3));
map.put("2", Arrays.asList(4, 5, 6));
map.put("3", Arrays.asList(7, 8, 9));
// 假设已经将数据存储到map中
List<Integer> list = map.values().stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// 将所有List<Object>对象中的元素合并成一个Stream,并将所有元素收集到一个新的List<Object>中
log.info(list.toString());
}
final List<StoreSkuInvSalDTO> collect = groupName_2_salDatas.values().stream()
.flatMap(x -> x.getProducts().stream())
.collect(Collectors.toList());
二.筛选
1.筛选是否存在
final boolean exist = value.stream()
.filter(x -> x.getFlag().equals(FlagEnum.RED.getCode())).collect(Collectors.toList()).size() > 0;
2.去重
//方式一
List<Long> distinctIdList = idList.stream().distinct().collect(Collectors.toList());
//方式二
final List<ProductAllexinfoV1DTO> invSqlSkus = tags.stream().filter(t -> t.getInvQty() > 0 || t.getSalQty() > 0).collect(Collectors.toList());
homeSkuTotal.setProductTotal(CollectionUtils.isEmpty(invSqlSkus) ? 0 :
invSqlSkus.stream().map(ProductAllexinfoV1DTO::getProductKey).collect(Collectors.toSet()).size());
3.最小最大
//最小值
final Integer minWeek = timeAxisDTOS.stream().min(Comparator.comparing(x -> x.getFinancialWeek())).get().getFinancialWeek();
//最大值
final Integer maxWeek = timeAxisDTOS.stream().max(Comparator.comparing(x -> x.getFinancialWeek())).get().getFinancialWeek();
4.找到第一个存在的
final Optional<AdsDimFinancialYearWeekInfoDO> first = dimList.stream().filter(t -> t.getFinancialYear().equals(finalYear)&& t.getFinancialYearWeek().equals(finalWeek)).findFirst();
if (first.isPresent()) {
final AdsDimFinancialYearWeekInfoDO yearWeekInfo = first.get();
}
5.并且筛选
final Set<String> headerFilterList = pageQuery.getHeaderFilterList();
if (CollectionUtils.isNotEmpty(headerFilterList)) {
tags = tags.stream().filter(t -> headerFilterList.contains("salQty") ? t.getSalQty() > 0 : true)
.filter(t -> headerFilterList.contains("replenishQty") ? t.getReplenishQty() > 0 : true)
.filter(t -> headerFilterList.contains("orderNotArriveQty") ? t.getOrderNotArriveQty() > 0 : true)
.filter(t -> headerFilterList.contains("replenishNotArriveQty") ? t.getReplenishNotArriveQty() > 0 : true)
.collect(Collectors.toList());
}
6.模糊筛选
final String productCode = pageQuery.getProductCode();
if (StringUtils.isNotEmpty(productCode)) {
tags = tags.stream().filter(t -> t.getProductCode() != null && t.getProductCode().indexOf(productCode) > -1).collect(Collectors.toList());
}
7.或者筛选
final Set<String> invQtyList = pageQuery.getInvQtyList();
if (CollectionUtils.isNotEmpty(invQtyList)) {
if (!invQtyList.contains("A") && !invQtyList.contains("B") && invQtyList.contains("C") && invQtyList.contains("D")) {
tags = tags.stream().filter(t -> t.getInvQty() >= 50)
.collect(Collectors.toList());
} else {
tags = tags.stream().filter(t ->
(invQtyList.contains("A") && t.getInvQty() <= 0) ||
(invQtyList.contains("B") && t.getInvQty() > 0 && t.getInvQty() < 50) ||
(invQtyList.contains("C") && t.getInvQty() > 50 && t.getInvQty() < 300) ||
(invQtyList.contains("D") && t.getInvQty() >= 300)
).collect(Collectors.toList());
}
}
8.找到最近一天
final Optional<CityAndRegionAndCountryBrandSkuRepDTO> max = orrSkus.stream().filter(t ->
StringUtils.isNotEmpty(t.getPeriod_sdate()) && StringUtils.isNotEmpty(skuRep.getPeriod_sdate()) && DateTimeUtils.dateDiff(DateTimeUtils.str2Date(t.getPeriod_sdate()), DateTimeUtils.str2Date(skuRep.getPeriod_sdate())) > 0) .max(Comparator.comparing(CityAndRegionAndCountryBrandSkuRepDTO::getPeriod_sdate));
if (max.isPresent()) {
final CityAndRegionAndCountryBrandSkuRepDTO periodSdateOrr = max.get();}
9.反射筛选
final Set<String> headerFilterList = pageQuery.getHeaderFilterList();
if (CollectionUtils.isNotEmpty(headerFilterList) && !headerFilterList.contains(CommonConstant.ALL)) {
for (String item : headerFilterList) {
if (StringUtils.equals("replenishQty", item) || StringUtils.equals("orderNotArriveQty", item) || StringUtils.equals("replenishNotArriveQty", item)) {
tags = tags.stream().filter(t -> Objects.nonNull(Reflect.on(t).field(item).get()) && (Integer) Reflect.on(t).field(item).get() != 0).collect(Collectors.toList());
} else {
tags = tags.stream().filter(t -> Objects.nonNull(Reflect.on(t).field(item).get()) && (Integer) Reflect.on(t).field(item).get() > 0).collect(Collectors.toList());
}
}
}
10.filter 过滤
//筛选符合条件的数据
List<DdlNode> collect = dagConf.getNodes().stream().filter(t -> NodeTypeEnum.OUT.name().equalsIgnoreCase(t.getType()))
.collect(Collectors.toList());
//或者条件
storeDay += dayStoreSkuSizeInvSalDTOList.stream().filter(p1 -> p1.getFlag() == 1 || p1.getFlag() == 3).count();
//并且条件
storeDay += dayStoreSkuSizeInvSalDTOList.stream().filter(p1 -> p1.getFlag() == 1 && p1.getFlag() == 3).count();
11.条件成立才过滤
products = products.stream()
.filter(x -> StringUtils.equals(x.getCategoryName1(), categoryName1))
.filter(x -> StringUtils.isEmpty(genderName) || StringUtils.equals(x.getGenderName(), genderName))
.filter(x -> StringUtils.equals(x.getIsnewFlag(), "0"))
.collect(Collectors.toList());
12.list 是否重复
public class Java8_13_stream_count {
public static void main(String[] args) {
List<Integer> list = new ArrayList() {
{
add(1);
add(2);
add(1);
}
};
long count = list.stream().distinct().count();
boolean isRepeat = count < list.size();
System.out.println(count);//输出2
System.out.println(isRepeat);//输出true
}
}
13.判断相同的元素
public class Java8_06_Stream_Same {
public static void main(String[] args) {
// 老师集合
List<Teacher> teachers = Arrays.asList(
new Teacher(1L, "张三"),
new Teacher(2L, "李四"),
new Teacher(3L, "王五"),
new Teacher(4L, "赵六"));
// 学生集合
List<Student> students = Arrays.asList(
new Student(5L, "张三"),
new Student(6L, "李四"),
new Student(7L, "小红"),
new Student(8L, "小明"));
// 求同时出现在老师集合和学生集合中的人数,name相同即视为同一个人
int size = (int) teachers.stream()
.map(t -> students.stream().filter(s -> Objects.nonNull(t.getName()) && Objects.nonNull(s.getName()) && Objects.equals(t.getName(), s.getName())).findAny().orElse(null))
.filter(Objects::nonNull).count();
// 求同时出现在老师集合和学生集合中人的name集合,name相同即视为同一个人
List<String> names = teachers.stream()
.map(t -> students.stream().filter(s -> Objects.nonNull(t.getName()) && Objects.nonNull(s.getName()) && Objects.equals(t.getName(), s.getName())).findAny().orElse(null))
.filter(Objects::nonNull)
.map(Student::getName)
.collect(Collectors.toList());
System.out.println("相同的人数:" + size);
System.out.println("相同的人姓名集合:" + names);
}
}
14.Match
- anyMatch: 匹配到任何一个元素和指定的元素相等,返回 true
- allMatch():匹配到全部元素和指定的元素相等,返回 true
- noneMatch():与 allMatch() 效果相反
List<String> strList = ListUtil.toList("a", "b", "c", "d");
boolean a = Optional.ofNullable(strList).orElseGet(ListUtil::toList)
.stream()
.anyMatch(obj -> obj.equals("a"));
System.out.println("anyMatch()测试多元素结果:" + a);
三.排序
1.单排序
properties.sort(Comparator.comparing(x -> x.distance));
list.sort(Comparator.comparing(UserInformation::getName));
//正序
list=list.stream().sorted().collect(Collectors.toList());
list.stream().sorted(Comparator.comparing(Student::getAge))
//逆序
list.stream().sorted(Comparator.reverseOrder())
list.stream().sorted(Comparator.comparing(Student::getAge).reversed())
2.双排序
timeAxisList.sort(Comparator.comparing(TimeAxisDTO::getFinancialYear).thenComparing(TimeAxisDTO::getFinancialWeek));
多字段排序:
list.sort(Comparator.comparing(UserInformation::getId).thenComparing(UserInformation::getAge));
多字段排序,指定正序还是倒序:
/**
* 按照推荐、置顶、发布时间来排序
* @param list
*/
private static void sort(List<Article> list){
List<Article> sortList = list.stream() .sorted(Comparator.comparing(Article::getRecommend,Comparator.reverseOrder())
.thenComparing(Article::getTop,Comparator.reverseOrder())
.thenComparing(Article::getReleaseTime,Comparator.reverseOrder()))
.collect(Collectors.toList());
sortList.stream().forEach(System.out::println);
}
3.自定义排序
List<String> sortListA = Arrays.asList("2023", "2022", "2021", "2020", "2019", "2018", "2017");
List<String> sortListB = Arrays.asList("春", "夏", "秋", "冬");
value = value.stream().sorted(Comparator.comparing(TotalListRegionSeasonDTO::getRegionNo, Comparator.comparing(sortListA::indexOf))
.thenComparing(TotalListRegionSeasonDTO::getSeasonName, Comparator.comparing(sortListB::indexOf))).collect(Collectors.toList());
4.反转排序
salListsTopN.sort(Comparator.comparing(SalList::getSalQty).reversed());
5.中文拼音排序
List<String> sortList = Arrays.asList("春", "夏", "秋", "冬");
Collator collator = Collator.getInstance(Locale.CHINA);
styleCategoryDim = styleCategoryDim.stream().sorted(Comparator.comparing(StyleCategoryDataDTO::getSeasonName, Comparator.comparing(sortList::indexOf))
.thenComparing(StyleCategoryDataDTO::getStyleCategoryName, collator)).collect(Collectors.toList());
6.list 嵌套排序
List<List<String>>排序
/**
* List<List<String>> 排序算法
*
* @author : qinyingjie
* @version : 2.2.0
* @date : 2022/12/12 11:22
*/
public class Java8_09_stream_sort {
private static List<List<String>> METHOD_LIST_WITH_ORDER = new LinkedList<>();
/**
* 按第n位降序排列
*
* @param compareIndex
*/
private static void doSortDesc(int compareIndex) {
for (int i = 0; i < METHOD_LIST_WITH_ORDER.size() - 1; i++) {
int preIndex = i;
int currentIndex = i + 1;
Long currentItem = Long.valueOf(METHOD_LIST_WITH_ORDER.get(currentIndex).get(compareIndex));
List<String> currentObject = METHOD_LIST_WITH_ORDER.get(currentIndex);
//当前节点的值大于前一节点,交换,且是循环比较
while (preIndex >= 0 && currentItem > Long.valueOf(METHOD_LIST_WITH_ORDER.get(preIndex).get(compareIndex))) {
METHOD_LIST_WITH_ORDER.set(preIndex + 1, METHOD_LIST_WITH_ORDER.get(preIndex));
preIndex--;
}
//设置preIndex + 1的值
METHOD_LIST_WITH_ORDER.set(preIndex + 1, currentObject);
}
}
public static void main(String[] args) {
METHOD_LIST_WITH_ORDER.add(Arrays.asList("1", "3", "4", "5"));
METHOD_LIST_WITH_ORDER.add(Arrays.asList("1", "3", "4", "4"));
METHOD_LIST_WITH_ORDER.add(Arrays.asList("1", "3", "4", "7"));
METHOD_LIST_WITH_ORDER.add(Arrays.asList("1", "3", "4", "1"));
METHOD_LIST_WITH_ORDER.add(Arrays.asList("2", "3", "4", "9"));
doSortDesc(3);
for (List<String> list : METHOD_LIST_WITH_ORDER) {
for (String s : list) {
System.out.print(s + ",");
}
System.out.println();
}
System.out.println(JSON.toJSONString(METHOD_LIST_WITH_ORDER));
}
}
7.多字段升降不定
final String sortName = pageQuery.getSortname();
final String sortOrd = pageQuery.getSortord();
tags = tags.stream().sorted(
("sal_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getSalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total7_sal_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotal7SalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total14_sal_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotal14SalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total28_sal_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotal28SalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total_sal_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotalSalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total_size_store_day".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotalSizeStoreDay, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"counter_date".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getCounterDate, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"inv_store_count".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getInvStoreCount, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total_sal_qty_store_rate".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotalSalQtyStoreRate, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"total30_sal_qty_store_rate".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getTotal30SalQtyStoreRate, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
"replenish_not_arrive_qty".equals(sortName) ? Comparator.comparing(ProductAllexinfoV1DTO::getReplenishNotArriveQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()) :
Comparator.comparing(ProductAllexinfoV1DTO::getSalQty, StringUtils.equals(sortOrd, "desc") ? Comparator.reverseOrder() : Comparator.naturalOrder()))
).collect(Collectors.toList());
8.含空值排序
list=list.stream().sorted(Comparator.comparing(l -> l.getCreateTime(), Comparator.nullsFirst(Date::compareTo))).collect(Collectors.toList());
List<Map<String, Object>> collect = maps.stream() .sorted(Comparator.comparing((Map<String, Object> o) -> (Double) o.get("score"),
Comparator.nullsLast(Comparator.reverseOrder()))
.thenComparing((Map<String, Object> o) -> ((double) o.get("dealerDistance")),
Comparator.nullsLast(Comparator.naturalOrder())))
.collect(Collectors.toList());
9.反射排序
public static void main(String[] args) {
final String sortName = "counterDate";
// final String sortOrd = "desc";
final String sortOrd = "asc";
List<ProductAllexinfoV1DTO> tags = new ArrayList<>();
ProductAllexinfoV1DTO do1 = new ProductAllexinfoV1DTO();
do1.setSalQty(26);
do1.setCounterDate("2023-01-01");
tags.add(do1);
ProductAllexinfoV1DTO do2 = new ProductAllexinfoV1DTO();
do2.setSalQty(233);
do2.setCounterDate(null);
tags.add(do2);
ProductAllexinfoV1DTO do3 = new ProductAllexinfoV1DTO();
do3.setSalQty(56);
do3.setCounterDate("2023-03-01");
tags.add(do3);
tags.sort((o1, o2) -> {
final Object object1 = Reflect.on(o1).field(sortName).get();
final Object object2 = Reflect.on(o2).field(sortName).get();
if (Objects.isNull(object1) && Objects.isNull(object2)) return 0;
if (Objects.isNull(object1)) return 1;
if (Objects.isNull(object2)) return -1;
if (object1 instanceof String) {
return StringUtils.equals(sortOrd, "desc") ? Comparator.<String>reverseOrder().compare((String) object1, (String) object2) :
Comparator.<String>naturalOrder().compare((String) object1, (String) object2);
} else if (object1 instanceof Integer) {
return StringUtils.equals(sortOrd, "desc") ? Comparator.<Integer>reverseOrder().compare((Integer) object1, (Integer) object2) :
Comparator.<Integer>naturalOrder().compare((Integer) object1, (Integer) object2);
} else if (object1 instanceof BigDecimal) {
return StringUtils.equals(sortOrd, "desc") ? Comparator.<BigDecimal>reverseOrder().compare((BigDecimal) object1, (BigDecimal) object2) :
Comparator.<BigDecimal>naturalOrder().compare((BigDecimal) object1, (BigDecimal) object2);
}
return 0;
});
System.out.println(JSONArray.toJSONString(tags));
}
测试filter:
public static void main(String[] args) {
final String sortName = "counterDate";
// final String sortOrd = "desc";
final String sortOrd = "asc";
List<ProductAllexinfoV1DTO> tags = new ArrayList<>();
ProductAllexinfoV1DTO do1 = new ProductAllexinfoV1DTO();
do1.setSalQty(26);
do1.setCounterDate("2023-01-01");
do1.setReplenishQty(111);
tags.add(do1);
ProductAllexinfoV1DTO do2 = new ProductAllexinfoV1DTO();
do2.setSalQty(233);
do2.setCounterDate(null);
do2.setReplenishQty(0);
tags.add(do2);
ProductAllexinfoV1DTO do3 = new ProductAllexinfoV1DTO();
do3.setSalQty(56);
do3.setCounterDate("2023-03-01");
do3.setReplenishQty(131);
tags.add(do3);
final Set<String> headerFilterList = new HashSet<>();
headerFilterList.add("replenishQty");
if (CollectionUtils.isNotEmpty(headerFilterList) && !headerFilterList.contains(CommonConstant.ALL)) {
for (String item : headerFilterList) {
if (StringUtils.equals("replenishQty", item) || StringUtils.equals("orderNotArriveQty", item) || StringUtils.equals("replenishNotArriveQty", item)) {
tags.stream().filter(t -> Objects.nonNull(Reflect.on(t).field(item).get()) && (Integer) Reflect.on(t).field(item).get() != 0).collect(Collectors.toList());
} else {
tags.stream().filter(t -> Objects.nonNull(Reflect.on(t).field(item).get()) && (Integer) Reflect.on(t).field(item).get() > 0).collect(Collectors.toList());
}
}
}
System.out.println(JSONArray.toJSONString(tags));
}
10.不用 stream
// 正序
list.sort(Comparator.comparing(Integer::intValue));
// 倒序
list.sort(Comparator.comparing(Integer::intValue).reversed());
// 正序
list.sort(Comparator.comparing(Student::getAge));
// 倒序
list.sort(Comparator.comparing(Student::getAge).reversed());
11.nullsLast
以 nullsLast()为例,项目逻辑中 dealerDistance 为 null 时排最后
Comparator.nullsLast(Comparator.reverseOrder())把 null 排序最后面,然后是 Comparator.reverseOrder(),null 值不参与逆序,null 还是在最后Comparator.nullsLast(Double ::compareTo).reversed() 先是把 null 排最后面,再整体 reversed(),包括为 null 的,所以 null 在最前面注:reverseOrder()是逆转排序即逆序,而 reversed()是逆转仔细理解,这两个在意思上还是有区别
13.根据 map 的 key 排序
要根据resultsMap
的键值对中的键(String
类型)进行降序排列,可以使用Comparator
接口来实现自定义比较器,并将其传递给TreeMap
类的构造函数。以下是一种实现方法:
public class Main {
public static void main(String[] args) {
// 创建一个示例的 Map
Map<String, List<StoreSalCalendarDTO>> resultsMap = new HashMap<>();
// 添加一些键值对
resultsMap.put("Key1", new ArrayList<>());
resultsMap.put("Key3", new ArrayList<>());
resultsMap.put("Key2", new ArrayList<>());
// 使用自定义比较器对键进行降序排列
Map<String, List<StoreSalCalendarDTO>> sortedMap = new TreeMap<>(new KeyComparator());
sortedMap.putAll(resultsMap);
// 打印排好序的 Map
for (Map.Entry<String, List<StoreSalCalendarDTO>> entry : sortedMap.entrySet()) {
System.out.println(entry.getKey());
}
}
static class KeyComparator implements Comparator<String> {
@Override
public int compare(String key1, String key2) {
// 降序排列
return key2.compareTo(key1);
}
}
}
在上述示例中,我们首先创建了一个示例的resultsMap
,其中包含一些键值对。然后,我们定义了一个名为KeyComparator
的内部类,实现了Comparator<String>
接口,用于比较键的值。在compare
方法中,我们通过使用key2.compareTo(key1)
实现了降序排列。最后,我们创建了一个新的TreeMap
实例,并传递了KeyComparator
对象作为参数。通过putAll
方法将原始的resultsMap
中的键值对放入新的sortedMap
中,以得到降序排列的结果。
在打印循环中,我们遍历排好序的sortedMap
的键,并将它们输出到控制台。
14.set 排序
storeSkuSizeInvTotalSalDTO.setSizeCodeList(new TreeSet<>(sizeCodes));
15.比较器特性
特殊错误:比较方法违反其一般合同
在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sort,Collections.sort会报 IllegalArgumentException 异常。
- 自反性:当 两个相同的元素相比时,compare 必须返回 0,也就是 compare(o1, o1) = 0;
- 反对称性:如果 compare(o1,o2) = 1,则 compare(o2, o1)必须返回符号相反的值也就是 -1;
- 传递性:如果 a>b, b>c, 则 a 必然大于 c。也就是 compare(a,b)>0, compare(b,c)>0, 则 compare(a,c)>0
final Object object1 = Reflect.on(o1).field(sortName).get();
final Object object2 = Reflect.on(o2).field(sortName).get();
if (Objects.isNull(object1) && Objects.isNull(object2)) return 0;
if (Objects.isNull(object1)) return 1;
if (Objects.isNull(object2)) return -1;
四.互转
1.抽取对象属性
List<Integer> ids = taskRecordDOList.stream().map(TaskRecordDO::getId).collect(Collectors.toList());
2.对象互转
List<DayStoreSkuSizeInvSalDTO> dtos = sizeInvSalList.stream()
.map(item -> {
DayStoreSkuSizeInvSalDTO dayStoreSkuSizeInvSalDTO = new DayStoreSkuSizeInvSalDTO();
BeanUtil.copyProperties(item, dayStoreSkuSizeInvSalDTO);
return dayStoreSkuSizeInvSalDTO;
}).collect(Collectors.toList());
3.属性转 set
转set:
final Set<String> sizeCodes = sizeInvSalList.stream().map(DayStoreSkuSizeInvSalDO::getSizeCode).collect(Collectors.toSet());
筛选转set:
final List<String> genderName = pageQuery.getGenderName();
if (CollectionUtils.isNotEmpty(genderName)) {
tags = tags.stream().filter(t -> genderName.contains(t.getGenderName()))
.collect(Collectors.toList());
}
4.分组转 map
Map<Integer, List<TimeAxisDTO>> yearLists = list.stream().collect(Collectors.groupingBy(TimeAxisDTO::getFinancialYear));
//多字段
Map<String, List<DayStoreSkuSizeInvSalDTO>> financialYearWeekInfo = sizeIndex.stream().collect(Collectors.groupingBy(p -> p.getFinancialYear() + ":" + p.getFinancialWeek()));
每个店铺的价格等级:
@Test
public void test12() {
//获取每个店铺的价格等级
Map<String, Integer> map = properties.stream()
.collect(Collectors.toMap(Property::getName, Property::getPriceLevel));
System.out.println(JSON.toJSONString(map));
}
@Test
public void test13() {
//所有价格等级的店铺列表
Map<Integer, List<Property>> priceMap = properties.stream()
.collect(Collectors.groupingBy(Property::getPriceLevel));
System.out.println(JSON.toJSONString(priceMap));
}
5.list 转 list
Map<Object, List<Student>> mapGroup = list.stream().collect(Collectors.groupingBy(v -> v.getName() + v.getAge()));
List<List<Student>> categorys = new ArrayList<>(mapGroup.values());
6.分组转 map
Map<String, List<TaskRecordDO>> collect1 = list.stream().collect(Collectors.groupingBy(TaskRecordDO::getOutNodeKey));
7.驼峰下划线
Gauva:
//驼峰转下划线
String ans = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, "helloWorld");
System.out.println(ans);
//下划线转驼峰
String ans2 = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "hello_world");
System.out.println(ans2);
Hutool:
String ans = StrUtil.toCamelCase("hello_world");
System.out.println(ans);
String ans2 = StrUtil.toUnderlineCase("helloWorld");
System.out.println(ans2);
实战:
//排序:驼峰转下划线
String sortname = query.getSortname();
if (StringUtils.isNotEmpty(sortname)) {
try {
BrandStoreSkuInvSalRateWeekDTO.class.getField(sortname);
sortname = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, sortname);
query.setSortname(sortname);
} catch (NoSuchFieldException e) {
log.error("排序字段不存在,排序字段为{}", sortname);
query.setSortname(null);
}
}
工具类:
public class ColumnUtil {
private static Pattern humpPattern = Pattern.compile("[A-Z]");
private static Pattern linePattern = Pattern.compile("_(\\w)");
/**
* 驼峰转下划线
* @param str
* @return
*/
public static String humpToLine(String str) {
Matcher matcher = humpPattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 下划线转驼峰
* @param str
* @return
*/
public static String lineToHump(String str) {
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}
8.toMap 重复 key
Map<Date, TimeAxisDTO> collect6 = timeAxisDTOListB.stream().collect(Collectors.
toMap(TimeAxisDTO::getPeriodSdate, timeAxisDTO -> timeAxisDTO, (key1, key2) -> key1));
9.list 合并
/**
* 多个list合并
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/9 10:33
*/
public class Java8_48_stream_merge_01 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
personList.add(new Person("Lily", 8800, 26, "male", "New York"));
personList.add(new Person("Alisa", 9000, 26, "female", "New York"));
List<Person> personList2 = new ArrayList<>();
personList2.add(new Person("Sherry", 9000, 24, "female", "New York"));
personList2.add(new Person("Tom", 8900, 22, "male", "Washington"));
personList2.add(new Person("Jack", 9000, 25, "male", "Washington"));
personList2.add(new Person("Lily", 8800, 26, "male", "New York"));
personList2.add(new Person("Alisa", 9000, 26, "female", "New York"));
List<List<Person>> list = new ArrayList<>();
list.add(personList);
list.add(personList2);
List<Person> persons = merge(list);
System.out.println(JSONArray.toJSONString(persons));
}
private static List<Person> merge(List<List<Person>> list) {
List<Person> persons = new ArrayList<>();
for (List<Person> people : list) {
for (Person person : people) {
persons.add(person);
}
}
return persons;
}
}
/**
* 多个list合并
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/9 10:33
*/
public class Java8_48_stream_merge_02 {
public static void main(String[] args) {
List<Integer> list = ImmutableList.of(1, 3, 5);
list = list.stream().flatMap(l -> {
List<Integer> list1 = new ArrayList<>();
list1.add(l + 1);
list1.add(l + 2);
return list1.stream();
}).collect(Collectors.toList());
System.out.println(list);// [2, 3, 4, 5, 6, 7]
}
}
/**
* 多个list合并
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/9 10:33
*/
public class Java8_48_stream_merge_03 {
public static void main(String[] args) {
List<List<Map<String, Object>>> lists = ImmutableList.of(
ImmutableList.of(
ImmutableMap.of("a", 1, "b", 2), ImmutableMap.of("a", 2, "b", 3)
),
ImmutableList.of(
ImmutableMap.of("a", 3, "b", 4), ImmutableMap.of("a", 4, "b", 5)
),
ImmutableList.of(
ImmutableMap.of("a", 5, "b", 6), ImmutableMap.of("a", 6, "b", 7)
)
);
// 将多个list合并为一个list
List<Map<String, Object>> list = lists.stream().flatMap(Collection::stream).collect(Collectors.toList());
System.out.println(JSONArray.toJSONString(list));
}
}
10.数组转 List
/**
* 数组转list Arrays.asList不能add
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/10 00:21
*/
public class Basic_collection_10_Array2List_01 {
public static void main(String[] args) {
String[] strArray = new String[2];
List list = Arrays.asList(strArray);
//对转换后的list插入一条数据
list.add("1");
System.out.println(list);
}
}
/**
* 数组转list
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/10 00:21
*/
public class Basic_collection_10_Array2List_02 {
public static void main(String[] args) {
String[] strArray = new String[2];
ArrayList<String> list = new ArrayList<String>(Arrays.asList(strArray));
list.add("1");
System.out.println(list);
}
}
/**
* 数组转list
*
* @author : kwan
* @version : 1.0.0
* @date : 2022/8/10 00:21
*/
public class Basic_collection_10_Array2List_03 {
public static void main(String[] args) {
String[] strArray = new String[2];
ArrayList< String> arrayList = new ArrayList<String>(strArray.length);
Collections.addAll(arrayList, strArray);
arrayList.add("1");
System.out.println(arrayList);
}
}
11.转对象
//转对象
Myclass myclass = JSONObject.parseObject(jsonStr , Myclass.class);// jsonStr 是String类型。
//转list对象
List<NewPxtOrder> pxtOrderList = JSONObject.parseArray(order,NewPxtOrder.class);
12.fastjson 不能转对象的情况
String redisKey = supplierRelateServiceManager.getRedisKey();
String checkOrderInfo = jedis.get(redisKey);
// SelfOrderModel selfOrderModel = JSONObject.parseObject(checkOrderInfo, SelfOrderModel.class);
// selfOrderModel.setRejectReason(outExamineVo.getRemark());
JSONObject jsonObject = JSONObject.parseObject(checkOrderInfo);
jsonObject.put("rejectReason", outExamineVo.getRemark());
jedis.set(redisKey, jsonObject.toJSONString());
13.多字段分组
分组:
Map<Integer, Map<Integer, List<StoreSalCalendarDTO>>> groupByYearMonth = results.stream().collect(Collectors.groupingBy(StoreSalCalendarDTO::getFinancialYear, Collectors.groupingBy(StoreSalCalendarDTO::getFinancialYearMonth)));
遍历:
Map<Integer, Map<Integer, List<StoreSalCalendarDTO>>> groupByYearMonth = new HashMap<>();
if (Objects.nonNull(groupByYearMonth)) {
groupByYearMonth.forEach((year, yearValue) -> {
if (Objects.nonNull(yearValue)) {
yearValue.forEach((month, monthValue) -> {
});
}
});
}
14.map 转 list
需要将 map 打平转为 list
final List<StoreSkuInvSalDTO> sal = groupName_2_salDatas.values().stream()
.flatMap(x -> x.getProducts().stream())
.collect(Collectors.toList());
15.List、String、Set 互转
//list转string
String str= String.join("','", list);
//list转set
Set<String> set = new HashSet<>(skuList);
//set转list
List<String> list = new ArrayList<>(set);
五.计算
1.汇总数据
homeSkuTotal.setTotal7SalQty(tags.stream().mapToInt(item -> Objects.nonNull(item.getTotal7SalQty()) ? item.getTotal7SalQty() : 0).sum());
if (CollectionUtils.isNotEmpty(homeSkuTotalOrr)) {
homeSkuTotalOrr.stream().mapToInt(AdsDayOrrDO::getOrderNotArriveQty).sum();
}
2.分组求和
分组求最大值再求和
if (CollectionUtils.isNotEmpty(homeSkuTotalOrr)) {
final Collection<Optional<AdsDayOrrDO>> values = homeSkuTotalOrr.stream().collect(Collectors.groupingBy(AdsDayOrrDO::getProductKey, Collectors.maxBy(Comparator.comparing(AdsDayOrrDO::getPeriodSdate)))).values();
homeSkuTotalDTO.setOrderNotArriveQty(values.stream().mapToInt(item -> item.get().getOrderNotArriveQty()).sum());
homeSkuTotalDTO.setReplenishNotArriveQty(values.stream().mapToInt(item -> item.get().getReplenishNotArriveQty()).sum());
}
3.BigDecimal
1.求和
BigDecimal sum = Arrays.stream(bdArray).reduce(BigDecimal.ZERO, (p, q) -> p.add(q));
BigDecimal sum = list.stream().map(Person::getWeight)
.reduce(BigDecimal.ZERO, BigDecimal::add);
2.自定义求和
BigDecimal sum = map.values().stream().reduce(BigDecimal.ZERO, Utility::addWeight);
import java.math.BigDecimal;
public class Utility {
public static BigDecimal addWeight(BigDecimal w1, BigDecimal w2) {
return w1.add(w2);
}
}
3.举例
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
public class BigDecimalSumUsingList {
public static void main(String[] args) {
Person p1 = new Person("AAA", new BigDecimal("45.23"));
Person p2 = new Person("BBB", new BigDecimal("55.43"));
Person p3 = new Person("CCC", new BigDecimal("65.21"));
Person p4 = new Person("DDD", new BigDecimal("35.73"));
List<Person> list = Arrays.asList(p1, p2, p3, p4);
BigDecimal sum = list.stream().map(Person::getWeight)
.reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println(sum);
sum = list.stream().map(p -> p.getWeight())
.reduce(BigDecimal.ZERO, (b1, b2) -> b1.add(b2));
System.out.println(sum);
sum = list.stream().map(Person::getWeight)
.reduce(BigDecimal.ZERO, Utility::addWeight);
System.out.println(sum);
}
}
BigDecimal求和
BigDecimal sum = products.stream()
.map(Product::getPrice)
.reduce(BigDecimal.ZERO, BigDecimal::add);
先相乘再累加:
final BigDecimal mgmtPrmAmt = value.stream()
.map(product -> product.getMgmtPrmAmt().multiply(new BigDecimal(product.getSalQty())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
4.获取前七天
public static void main(String[] args) {
List<String> dates = new ArrayList<>();
final DateTime yesterdayDate = DateUtil.yesterday();
final String yesterday = DateUtil.formatDate(yesterdayDate);
dates.add(yesterday);
for (int i = 1; i < 7; i++) {
final DateTime dateTime = DateUtil.offsetDay(yesterdayDate, -i);
dates.add(DateUtil.formatDate(dateTime));
}
for (String date : dates) {
System.out.println(date);
}
}
5.内存分页
pageBean.setTotalElements(tags.size());
pageBean.setTotalPages(tags.size() / pageQuery.getSize() + (tags.size() % pageQuery.getSize() == 0 ? 0 : 1));
pageBean.setSize(pageQuery.getSize());
pageBean.setNumber(pageQuery.getPage());
pageBean.setContent(tags.stream().skip((pageQuery.getPage() - 1) * pageQuery.getSize()).limit(pageQuery.getSize()).collect(Collectors.toList()));
pageBean.setNumberOfElements(CollectionUtils.isNotEmpty(pageBean.getContent()) ? pageBean.getContent().size() : 0L);
6.判断集合为空
CollectionUtils.isNotEmpty({a,b}): true
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.2</version>
</dependency>
7.每一天的 top30
你这个问题有点不明确,不知道是什么数据需要排名,下面我以网站访问量为例,给出一种计算每天 top30 访问量的方法。
假设你有一个这样的数据文件,每一行表示某一天某个网站的访问量:
2022-01-01,website1,100
2022-01-01,website2,200
2022-01-01,website3,300
2022-01-02,website1,150
2022-01-02,website2,250
2022-01-02,website3,350
2022-01-03,website1,180
2022-01-03,website2,280
2022-01-03,website3,380
你可以按照日期进行分组,然后对每一组的数据按照访问量排序,取前 30 就是每一天的 top30 访问量。下面是一段 Java 代码实现这个逻辑:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Top30ByDay {
public static class Record {
private Date date;
private String website;
private int visits;
public Record(Date date, String website, int visits) {
this.date = date;
this.website = website;
this.visits = visits;
}
public Date getDate() {
return date;
}
public String getWebsite() {
return website;
}
public int getVisits() {
return visits;
}
}
public static void main(String[] args) throws IOException {
// 读取数据文件
List<Record> records = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
String[] fields = line.split(",");
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(fields[0]);
String website = fields[1];
int visits = Integer.parseInt(fields[2]);
Record record = new Record(date, website, visits);
records.add(record);
}
}
// 按照日期分组,计算每一天的top30访问量
Map<Date, List<Record>> groupByDate = records.stream()
.collect(Collectors.groupingBy(Record::getDate));
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
for (Map.Entry<Date, List<Record>> entry : groupByDate.entrySet()) {
Date date = entry.getKey();
List<Record> recordsByDay = entry.getValue();
List<Record> top30ByDay = recordsByDay.stream()
.sorted(Comparator.comparingInt(Record::getVisits).reversed())
.limit(30)
.collect(Collectors.toList());
System.out.println(dateFormat.format(date) + " top 30:");
for (Record record : top30ByDay) {
System.out.println(record.getWebsite() + " " + record.getVisits());
}
System.out.println();
}
}
}
这个代码使用 Java 8 的 Stream API,将数据按照日期分组,然后对每一组的数据按照访问量排序并取前 30,输出每一天的 top30 访问量。在这个例子中,我使用了 Java 的日期处理库java.util.Date
和java.text.SimpleDateFormat
,你可以根据自己的需求替换成其他日期处理库。
8.并行处理
@Test
public void test15() {
// 调用 parallelStream 方法即能并行处理
List<String> names = properties.parallelStream()
.filter(p -> p.priceLevel < 4)
.sorted(Comparator.comparingInt(Property::getDistance))
.map(Property::getName)
.limit(2)
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(names));
}
六.jackson 使用
1.依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
2.json 字符串转对象
/**
* 字符串转对象
*
* @throws Exception
*/
@Test
public void test1() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
Car car = objectMapper.readValue(carJson, Car.class);
System.out.println(objectMapper.writeValueAsString(car));
}
3.对象转 json 字符串
/**
* 对象转字符串
*
* @throws Exception
*/
@Test
public void test2() throws Exception {
Car car = new Car();
car.setBrand("宝马");
car.setDoors(8);
System.out.println(new ObjectMapper().writeValueAsString(car));
}
4.二进制数组转 json 对象
/**
* 二进制数组转对象
*
* @throws Exception
*/
@Test
public void test3() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
byte[] bytes = carJson.getBytes("UTF-8");
Car car = objectMapper.readValue(bytes, Car.class);
System.out.println(objectMapper.writeValueAsString(car));
}
5.json 字符串转 list 集合
/**
* 字符串转lsit
*
* @throws Exception
*/
@Test
public void test4() throws Exception {
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> cars = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>() {
});
System.out.println(objectMapper.writeValueAsString(cars));
}
6.list 转 json 字符串
/**
* list转字符串
*
* @throws Exception
*/
@Test
public void test5() throws Exception {
List<Car> cars = new ArrayList<>();
Car car1 = new Car();
car1.setBrand("宝马");
car1.setDoors(8);
cars.add(car1);
Car car2 = new Car();
car2.setBrand("奔驰");
car2.setDoors(10);
cars.add(car2);
System.out.println(new ObjectMapper().writeValueAsString(cars));
}
7.json 字符串转 map
/**
* 字符串转map
*
* @throws Exception
*/
@Test
public void test6() throws Exception {
String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> jsonMap = objectMapper.readValue(jsonObject,
new TypeReference<Map<String, Object>>() {
});
System.out.println(objectMapper.writeValueAsString(jsonMap));
}
七.函数式接口
1.新接口
以下是一些常用的函数式接口:
- Supplier (
java.util.function.Supplier<T>
):表示一个供应商,它不接受参数,但返回一个值。在函数式编程中,常用于延迟计算或提供初始值。 - Function (
java.util.function.Function<T, R>
):表示一个函数,它接受一个参数类型为T
的对象,然后返回一个类型为R
的结果对象。 - Predicate (
java.util.function.Predicate<T>
):表示一个断言,它接受一个参数类型为T
的对象,返回一个布尔值,用于判断对象是否满足某个条件。 - UnaryOperator (
java.util.function.UnaryOperator<T>
):是一个特殊的Function
,输入和输出类型都是相同的。用于表示只接受一个参数并返回相同类型结果的操作。 - BinaryOperator (
java.util.function.BinaryOperator<T>
):是一个特殊的Function
,输入和输出类型都是相同的。用于表示接受两个参数并返回一个相同类型结果的操作。 - BiFunction (
java.util.function.BiFunction<T, U, R>
):与Function
类似,但接受两个参数类型分别为T
和U
的对象,然后返回一个类型为R
的结果对象。 - Consumer 接口的变种: 除了常规的
Consumer
,还有IntConsumer
、LongConsumer
、DoubleConsumer
分别用于处理整数、长整数和双精度浮点数。
这些函数式接口可以通过 Java 8 中的 java.util.function
包来使用,它们在函数式编程和 Lambda 表达式的应用中非常有用,可以让代码更加简洁和易于理解。
2.Consumer
Consumer
可以在函数式编程中的很多场景中使用,例如遍历集合并执行某种操作,执行异步任务的回调等。
是的,除了 Consumer
,Java 8 引入了一系列函数式接口,用于支持不同类型的函数式操作。
在 Java 8 中,Consumer
是一个函数式接口,它定义了一个接受一个参数并且不返回任何结果的操作。它在函数式编程中常用于表示一个可以对传入的参数执行某种操作的函数。
Consumer
接口有一个抽象方法 accept(T t)
,该方法接受一个参数类型为 T
的对象,并对该对象进行操作,但不返回任何结果。
下面是 Consumer
的简单示例:
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
// 使用 Consumer 打印字符串
Consumer<String> printConsumer = str -> System.out.println(str);
printConsumer.accept("Hello, world!");
// 使用 Consumer 修改集合中的元素
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
Consumer<List<String>> modifyConsumer = list -> {
for (int i = 0; i < list.size(); i++) {
list.set(i, list.get(i).toUpperCase());
}
};
modifyConsumer.accept(names);
System.out.println(names); // 输出: [ALICE, BOB, CHARLIE]
}
}
在上面的示例中,我们创建了两个不同的 Consumer
实例,一个用于打印字符串,另一个用于将集合中的元素转换为大写。accept
方法负责执行相应的操作。