java8新特性

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: java8新特性

一.JDK8 的增强

1.jdk8 增强与新特性

Java 8 引入了许多新的语言特性和 API 改进,以下是其中一些主要的特性:

  1. Lambda 表达式: Lambda 表达式是一种更简洁的语法,用于表示一个匿名函数。它使得在集合操作、事件处理等场景下代码更具可读性和简洁性。
  2. 函数式接口: Java 8 引入了函数式接口的概念,这是只包含一个抽象方法的接口。Lambda 表达式可以与函数式接口一起使用。
  3. 方法引用: 方法引用允许你直接引用现有的方法或构造函数,从而使代码更加简洁。
  4. 默认方法和静态方法: 接口现在可以包含默认方法和静态方法的实现。这使得在接口中添加新的方法时,不会破坏已有的实现。
  5. Stream API: Stream API 提供了一种更便捷的方式来处理集合数据。它支持函数式编程风格,可以用于过滤、映射、归约等操作。
  6. 新的日期和时间 API: Java 8 引入了 java.time 包,提供了全新的日期和时间 API,解决了旧的 DateCalendar 类存在的问题。
  7. Optional 类:Optional 是一个容器类,用于表示一个值可能存在,也可能不存在的情况,从而减少空指针异常的发生。
  8. Nashorn 引擎: Nashorn 是一个新的轻量级、高性能的 JavaScript 引擎,用于在 Java 程序中执行 JavaScript 代码。
  9. 新的重复注解和类型注解: 如前所述,Java 8 引入了对多重注解的支持,以及更丰富的类型注解。
  10. PermGen 空间被移除: Java 8 中,永久代(PermGen)被元空间(Metaspace)所取代,用于存放类的元数据。

2.Stream 的组成与特点

Stream(流)是一个来自数据源的元素队列并支持聚合操作:

  • 元素是特定类型的对象,形成一个队列。Java中的Stream不会向集合那样存储和管理元素,而是按需计算
  • 数据源流的来源可以是集合Collection、数组ArrayI/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.Datejava.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.新接口

以下是一些常用的函数式接口:

  1. Supplier (java.util.function.Supplier<T>):表示一个供应商,它不接受参数,但返回一个值。在函数式编程中,常用于延迟计算或提供初始值。
  2. Function (java.util.function.Function<T, R>):表示一个函数,它接受一个参数类型为 T 的对象,然后返回一个类型为 R 的结果对象。
  3. Predicate (java.util.function.Predicate<T>):表示一个断言,它接受一个参数类型为 T 的对象,返回一个布尔值,用于判断对象是否满足某个条件。
  4. UnaryOperator (java.util.function.UnaryOperator<T>):是一个特殊的 Function,输入和输出类型都是相同的。用于表示只接受一个参数并返回相同类型结果的操作。
  5. BinaryOperator (java.util.function.BinaryOperator<T>):是一个特殊的 Function,输入和输出类型都是相同的。用于表示接受两个参数并返回一个相同类型结果的操作。
  6. BiFunction (java.util.function.BiFunction<T, U, R>):与 Function 类似,但接受两个参数类型分别为 TU 的对象,然后返回一个类型为 R 的结果对象。
  7. Consumer 接口的变种: 除了常规的 Consumer,还有 IntConsumerLongConsumerDoubleConsumer 分别用于处理整数、长整数和双精度浮点数。

这些函数式接口可以通过 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 方法负责执行相应的操作。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
66 2
|
2月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
41 3
|
2月前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
33 2
|
2月前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
34 3
|
2月前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
84 1
|
2月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
82 3
|
22天前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
30 4
|
2月前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
72 3
|
2月前
|
存储 安全 Java
Java Map新玩法:深入探讨HashMap和TreeMap的高级特性
【10月更文挑战第19天】Java Map新玩法:深入探讨HashMap和TreeMap的高级特性,包括初始容量与加载因子的优化、高效的遍历方法、线程安全性处理以及TreeMap的自然排序、自定义排序、范围查询等功能,助你提升代码性能与灵活性。
26 2
|
2月前
|
Java 开发者
在Java的集合世界里,Set以其独特的特性脱颖而出,它通过“哈希魔法”和“红黑树防御”两大绝技
【10月更文挑战第13天】在Java的集合世界里,Set以其独特的特性脱颖而出。它通过“哈希魔法”和“红黑树防御”两大绝技,有效抵御重复元素的侵扰,确保集合的纯洁性和有序性。无论是“人海战术”还是“偷梁换柱”,Set都能从容应对,成为开发者手中不可或缺的利器。
31 6