java8中的map怎么根据value值进行排序
创始人
2024-11-21 17:21:31
0次

实现代码如下:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.LinkedHashMap;
 
public class MapSorted{
 
  public static void main(String[] args) {
    
    Map map = new HashMap<>();
    map.put("A", 3);
    map.put("B", 5);
    map.put("C", 1);
    map.put("D", 1);
    map.put("E", 9);
    
    System.out.println(map);
 
    //如果value为java对象,则需要实现Comparable接口,重写compareTo方法
 
    Map sortedMap = new LinkedHashMap<>();
    Map sortedMap2 = new LinkedHashMap<>();
 
    //ASC
    map.entrySet().stream()
      .sorted(Map.Entry.comparingByValue())
      .forEachOrdered(x -> sortedMap.put(x.getKey(), x.getValue()));
 
    System.out.println(sortedMap);
 
    //DESC Collections.reverseOrder || reversed()
    map.entrySet().stream()
    .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
    .forEachOrdered(x -> sortedMap2.put(x.getKey(), x.getValue()));
 
    // map.entrySet().stream()
    // .sorted(Map.Entry.comparingByValue().reversed())
    // .forEachOrdered(x -> sortedMap2.put(x.getKey(), x.getValue()));
 
    System.out.println(sortedMap2);
 
    //Collectors.toMap 直接返回排好序的map
    map =  map.entrySet().stream()
          .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
          .collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue(), (x1, x2) -> x2, LinkedHashMap::new));
    
    // map =  map.entrySet().stream()
    // .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
    // .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x1, x2) -> x2, LinkedHashMap::new));
    System.out.println(map);
  }
}
{A=3, B=5, C=1, D=1, E=9}
{C=1, D=1, A=3, B=5, E=9}
{E=9, B=5, A=3, C=1, D=1}
{E=9, B=5, A=3, C=1, D=1}

补充知识:对BeanCopier拷贝对象中List类型属性的思考

背景

最近开发接口过程中,使用BeanCopier拷贝对象,当对象中嵌套自定义对象类型属性的时候,

如果对象名称一致,但是对象类型不一致,拷贝的时候,该属性是会被忽略的,但是当对象中嵌套List集合类型属性(集合中是不同的对象类型)时,使用BeanCopier拷贝之后,返回给前台的数据是正确的,感觉不太懂其中的原理,就测试了下。

测试过程

新建几个对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassA {
  private String id;
  private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassB {
  private String id;
  private String name;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BeanA {
  private String name;
  private List aList;
}F
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BeanA1 {
  private String name;
  private ClassA className;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BeanB {
  private String name;
  private List aList;
}
Data
@NoArgsConstructor
@AllArgsConstructor
public class BeanB1 {
  private String name;
  private ClassB className;
}

拷贝BeanA1到BeanB1

public static void main(String[] args) {
  /**
   * 将cglib生成的代理类的class文件打印到指定目录
   */
  System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/haiyoung/logs");
  BeanA1 beanA1 = new BeanA1();
  beanA1.setName("aaa");
  beanA1.setClassName(new ClassA("001", "001"));
  BeanB1 beanB1 = new BeanB1();
  BeanCopier beanCopier = BeanCopier.create(BeanA1.class, BeanB1.class,false);
  beanCopier.copy(beanA1, beanB1,null);
  System.out.println(beanB1);
}

转换结果如下图所示:对象类型被忽略

java8中的map怎么根据value值进行排序

cglib生成的代理类如下所示

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.cglib.empty;
import com.haiyoung.hyweb.beanCopier.BeanA1;
import com.haiyoung.hyweb.beanCopier.BeanB1;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
public class Object$$BeanCopierByCGLIB$$c00337e1 extends BeanCopier {
  public Object$$BeanCopierByCGLIB$$c00337e1() {
  }
  public void copy(Object var1, Object var2, Converter var3) {
    ((BeanB1)var2).setName(((BeanA1)var1).getName());
  }
}

从copy实现代码中可以看到,不同对象类型属性间的拷贝被忽略

拷贝BeanA到BeanB

public static void main(String[] args) {
    /**
     * 将cglib生成的代理类的class文件打印到指定目录
     */
    System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/Users/haiyoung/logs");
    BeanA beanA = new BeanA();
    beanA.setName("aaa");
    List list = new ArrayList<>();
    list.add(new ClassA("001", "001"));
    beanA.setAList(list);
    BeanB beanB = new BeanB();
    BeanCopier beanCopier = BeanCopier.create(BeanA.class, BeanB.class,false);
    beanCopier.copy(beanA, beanB,null);
    System.out.println(beanB);
    List list1 = beanB.getAList();
    System.out.println(list1);
//    ClassB classB = list1.get(0);
//
//    System.out.println(classB);
  }

转换结果如下图所示,list对象类型属性被成功赋值

java8中的map怎么根据value值进行排序

但是对象beanA和benaB中的List属性,指向相同的引用,当用ClassB接收beanB中的List属性中的对象时,

会报对象强转失败

Exception in thread "main" [ClassA(id=001, name=001)]
java.lang.ClassCastException: com.haiyoung.hyweb.beanCopier.ClassA cannot be cast to com.haiyoung.hyweb.beanCopier.ClassB
 at com.haiyoung.hyweb.beanCopier.CopyTest.main(CopyTest.java:44)

cglib生成的代理类如下所示

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.cglib.empty;
import com.haiyoung.hyweb.beanCopier.BeanA;
import com.haiyoung.hyweb.beanCopier.BeanB;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
public class Object$$BeanCopierByCGLIB$$27129331 extends BeanCopier {
  public Object$$BeanCopierByCGLIB$$27129331() {
  }
  public void copy(Object var1, Object var2, Converter var3) {
    BeanB var10000 = (BeanB)var2;
    BeanA var10001 = (BeanA)var1;
    var10000.setAList(((BeanA)var1).getAList());
    var10000.setName(var10001.getName());
  }
}

从copy的实现代码中可以看到,两个对象中的List类型的对象集合属性被成功赋值,但是是引用赋值

结论

BeanCopier对不同对象中的List对象集合类型的属性的拷贝是弱拷贝,而不是深拷贝,如果只是做对象拷贝,然后直接抛出这个对象给前台使用是没有问题的,但是如果这个通过拷贝得到的对象要在代码中进行业务流转,则会报java.lang.ClassCastException 类强转异常

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...