JAVA8新特性集

lijunyi2023-12-15javaJAVA8

Stream流🎇

filter使用

//如果满足条件的对象存在
User user = userList.stream()
    .filter(t -> 1 == t.getId())
    .findAny()
    .get();

//如果对象不存在,则会抛出异常:java.util.NoSuchElementException: No value present
User e = userList.stream()
    .filter(t -> 3 == t.getId())
    .findAny()
    .get();
      
//如果对象不存在则返回特定对象
User n = userList.stream()
    .filter(t -> 3 == t.getId())
    .findAny()
    .orElse(null);

//判断对象是否存在
boolean b = userList.stream()
    .filter(t -> 3 == t.getId())
    .findAny()
    .isPresent();

// 示例三:通过与 mapToInt 计算和
List<User> lists = new ArrayList<User>();
lists.add(new User(6, "张三"));
lists.add(new User(2, "李四"));
lists.add(new User(3, "王五"));
lists.add(new User(1, "张三"));
// 计算这个list中出现 "张三" id的值
int sum = lists.stream()
    .filter(u -> "张三".equals(u.getName()))
    .mapToInt(u -> u.getId()).sum();

flatMap使用

// Stream流的flatMap使用
// flatMap 方法用于映射每个元素到对应的结果,一对多

String worlds = "The way of the future";
List<String> list7 = new ArrayList<>();
list7.add(worlds);

List<String> list8 = list7.stream()
   .flatMap(str -> Stream.of(str.split(" ")))
   .filter(world -> world.length() > 0)
   .collect(Collectors.toList());

limit使用

//示例一:获取前n条数的数据
Random rd = new Random();
System.out.println("取到的前三条数据:");
rd.ints().limit(3).forEach(System.out::println);

// 示例二:结合skip使用得到需要的数据:skip表示的是扔掉前n个元素
List<User> list9 = new ArrayList<User>();
 for (int i = 1; i < 4; i++) {
  User user = new User(i, "pancm" + i);
  list9.add(user);
 }

System.out.println("截取之前的数据:");
// 取前3条数据,但是扔掉了前面的2条,可以理解为拿到的数据为 2<=i<3 (i 是数值下标)
List<String> list10 = list9.stream()
    .map(User::getName)
    .limit(3)
    .skip(2)
    .collect(Collectors.toList());
 System.out.println("截取之后的数据:" + list10);
//  截取之前的数据:
//  姓名:pancm1
//  姓名:pancm2
//  姓名:pancm3
//  截取之后的数据:[pancm3]

sort使用

1、单字段排序

//按年龄排序(Integer类型)-正序
List<StudentInfo> studentsSortName = studentList.stream()
    .sorted(Comparator.comparing(StudentInfo::getAge))
    .collect(Collectors.toList());

//按年龄排序(Integer类型)-逆序
List<StudentInfo> studentsSortName = studentList.stream()
    .sorted(Comparator.comparing(StudentInfo::getAge)
    .reversed())
    .collect(Collectors.toList());

2、多字段排序

List<StudentInfo> list = userList.stream()
    .sorted(Comparator.comparing(UserDto::getUserRoleZt,Comparator.nullsLast(Integer::compareTo))
    .thenComparing(UserDto::getUserStatus)
    // reversed 降序
    .reversed())
    .collect(Collectors.toList());

3、对Null值进行排序

// 对象属性可能存在null值,不进行处理则会报NPE异常
// nullsLast:null值排在后面
// nullsFirst:null值排在前面
List<StudentInfo> list =userList.stream()
   .sorted(Comparator.comparing(UserDto::getUserRoleZt,Comparator.nullsLast(Integer::compareTo))
   .reversed())
   .collect(Collectors.toList());

4、List<Map<String, Object>> 排序

List<Map<String, Object>> cats = new ArrayList<>();
Map<String,Object> cat1 = new HashMap<>();
cat1.put("name", "cat1");
cat1.put("age", 10);
cats.add(cat1);

Map<String,Object> cat2 = new HashMap<>();
cat2.put("name", "cat2");
cat2.put("age", 2);
cats.add(cat2);

List<Map<String, Object>> sortedCats = cats.stream().sorted((map1, map2) -> {
    int age1 = (int) map1.getOrDefault("age", 0);
    int age2 = (int) map2.getOrDefault("age", 0);
    return age1 - age2;
}).collect(Collectors.toList());

sortedCats.forEach(System.out::println);

5、其他示例

// 示例一:随机取值排序
Random rd2 = new Random();
System.out.println("取到的前三条数据然后进行排序:");
rd2.ints().limit(3).sorted().forEach(System.out::println);


// 示例二:优化排序  tips:先获取在排序效率会更高!

//普通的排序取值
List<User> list11 = list9.stream()
    .sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
    .limit(3)
    .collect(Collectors.toList());

//优化排序取值
List<User> list12 = list9.stream()
    .limit(3)
    .sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
    .collect(Collectors.toList());

peek使用

peek对每个元素执行操作并返回一个新的Stream

// 示例:双重操作
 Stream.of("one", "two", "three", "four")
     .filter(e -> e.length() > 3)
     .peek(e -> System.out.println("转换之前: " + e))
     .map(String::toUpperCase)
     .peek(e -> System.out.println("转换之后: " + e))
     .collect(Collectors.toList());
 
 // 转换之前: three
 // 转换之后: THREE
 // 转换之前: four
 // 转换之后: FOUR

max/min/distinct使用

// 示例一:得到最大最小值
List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xiwqjing");

int maxLines = list13.stream()
    .mapToInt(String::length)
    .max()
    .getAsInt();

int minLines = list13.stream()
    .mapToInt(String::length)
    .min()
    .getAsInt();
System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
//最长字符的长度:8,最短字符的长度:4

//示例二:得到去重之后的数据
String lines = "good good study day day up";
List<String> list14 = new ArrayList<String>();
list14.add(lines);

List<String> words = list14.stream()
    .flatMap(line -> Stream.of(line.split(" ")))
    .filter(word -> word.length() > 0)
    .map(String::toLowerCase)
    .distinct()
    .sorted()
    .collect(Collectors.toList());
System.out.println("去重复之后:" + words);
//去重复之后:[day, good, study, up]

Match使用

  • allMatch:Stream 中全部元素符合则返回 true ;

  • anyMatch:Stream 中只要有一个元素符合则返回 true;

boolean all = lists.stream()
    .allMatch(u -> u.getId() > 3);
System.out.println("是否都大于3:" + all);

boolean any = lists.stream()
    .anyMatch(u -> u.getId() > 3);
System.out.println("是否有一个大于3:" + any);

boolean none = lists.stream()
    .noneMatch(u -> u.getId() > 3);
System.out.println("是否没有一个大于3的:" + none);  

 // 是否都大于3:false
 // 是否有一个大于3:true
 // 是否没有一个大于3的:false

reduce使用

reduce 主要作用是把 Stream 元素组合起来进行操作

// 示例一:字符串连接
String concat = Stream.of("A", "B", "C", "D")
    .reduce("", String::concat);
System.out.println("字符串拼接:" + concat);

// 示例二:得到最小值
double minValue = Stream.of(-4.0, 1.0, 3.0, -2.0)
    .reduce(Double.MAX_VALUE, Double::min);
System.out.println("最小值:" + minValue);
//最小值:-4.0

// 示例三:求和
// 求和, 无起始值
int sumValue = Stream.of(1, 2, 3, 4)
    .reduce(Integer::sum)
    .get();
System.out.println("有无起始值求和:" + sumValue);

// 求和, 有起始值
sumValue = Stream.of(1, 2, 3, 4)
    .reduce(1, Integer::sum);
System.out.println("有起始值求和:" + sumValue);
// 有无起始值求和:10
// 有起始值求和:11

//示例四:过滤拼接
concat = Stream.of("a", "B", "c", "D", "e", "F")
    .filter(x -> x.compareTo("Z") > 0)
    .reduce("", String::concat);

System.out.println("过滤和字符串连接:" + concat);
//过滤和字符串连接:ace

groupingBy/partitioningBy使用

  • groupingBy:分组排序

  • partitioningBy:分区排序

// 示例一:分组排序
Map<Integer, List<User>> personGroups = Stream.generate(new UserSupplier2())
    .limit(5)
   .collect(Collectors.groupingBy(User::getId));

 Iterator it = personGroups.entrySet().iterator();
 while (it.hasNext()) {
  Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
  System.out.println("id " + persons.getKey() + " = " + persons.getValue());
 }
 
 // 通过id进行分组排序:
 // id 10 = [{"id":10,"name":"pancm1"}] 
 // id 11 = [{"id":11,"name":"pancm3"}, {"id":11,"name":"pancm6"}, {"id":11,"name":"pancm4"}, {"id":11,"name":"pancm7"}]



 class UserSupplier2 implements Supplier<User> {
  private int index = 10;
  private Random random = new Random();
 
  @Override
  public User get() {
   return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
  }
   return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
 }


// 示例二:分区排序
System.out.println("通过年龄进行分区排序:");
 Map<Boolean, List<User>> children = Stream.generate(new UserSupplier3())
     .limit(5)
     .collect(Collectors.partitioningBy(p -> p.getId() < 18));

 System.out.println("小孩: " + children.get(true));
 System.out.println("成年人: " + children.get(false));
 
 // 通过年龄进行分区排序:
 // 小孩: [{"id":16,"name":"pancm7"}, {"id":17,"name":"pancm2"}]
 // 成年人: [{"id":18,"name":"pancm4"}, {"id":19,"name":"pancm9"}, {"id":20,"name":"pancm6"}]

  class UserSupplier3 implements Supplier<User> {
  private int index = 16;
  private Random random = new Random();
 
  @Override
  public User get() {
   return new User(index++, "pancm" + random.nextInt(10));
  }
 }

List根据某个属性去重

方法一:利用stream构建TreeSet进行去重

cgEndList = cgEndList.stream()
    .collect(Collectors.collectingAndThen(
                    Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(CgModel::getCgId))
                    ), ArrayList::new));

方法二:Predicate断言接口方式进行去重

List<CgDto> result = new ArrayList<>();
            endData.stream()
                    .filter(distinctByKey(CgDto::getCgId))
                    .forEach(result::add);

static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
    Map<Object,Boolean> seen = new ConcurrentHashMap<>();
    //putIfAbsent方法添加键值对,如果map集合中没有该key对应的值,则直接添加,并返回null,如果已经存在对应的值,则依旧为原来的值。
    //如果返回null表示添加数据成功(不重复),不重复(null==null :TRUE)
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

获取ID最大的对象

DyCgExpertDto maxExpertId = dyCgExpertDtos.stream()
        .max(Comparator.comparing(DyCgExpertDto::getId)).get();

循环两个list进行条件匹配给其中一个list对象的某个属性赋值

 List<CgModel> cgs = cgList.stream()
                .map(cg -> nodeInfos.stream()
                        .filter(node -> cg.getDqjdId().equals(node.getNodeId()))
                        .findFirst()
                        .map(node -> {
                            cg.setNodeName(node.getNodeName());
                            return cg;
                        }).orElse(cg))
                .collect(Collectors.toList());

合计BigDecimal金额

BigDecimal totalMoney = fkdModelList.stream()
                    .map(FkdModel::getCountMoney)
                    .reduce(BigDecimal.ZERO,BigDecimal::add);

交集差集并集

public class Test {
 
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>();
        list1.add("1");
		list1.add("2");
		list1.add("3");
		list1.add("5");
		list1.add("6");
 
        List<String> list2 = new ArrayList<String>();
        list2.add("2");
		list2.add("3");
		list2.add("7");
		list2.add("8");
 
        // 交集
        List<String> intersection = list1.stream()
            .filter(item -> list2.contains(item))
            .collect(toList());
        System.out.println("---交集 intersection---");
        intersection.parallelStream().forEach(System.out :: println);
 
        // 差集 (list1 - list2)
        List<String> reduce1 = list1.stream()
            .filter(item -> !list2.contains(item))
            .collect(toList());
        System.out.println("---差集 reduce1 (list1 - list2)---");
        reduce1.parallelStream().forEach(System.out :: println);
 
        // 差集 (list2 - list1)
        List<String> reduce2 = list2.stream()
            .filter(item -> !list1.contains(item))
            .collect(toList());
        System.out.println("---差集 reduce2 (list2 - list1)---");
        reduce2.parallelStream().forEach(System.out :: println);
 
        // 并集
        List<String> listAll = list1.parallelStream().collect(toList());
        List<String> listAll2 = list2.parallelStream().collect(toList());
        listAll.addAll(listAll2);
        System.out.println("---并集 listAll---");
        listAll.parallelStream().forEachOrdered(System.out :: println);
 
        // 去重并集
        List<String> listAllDistinct = listAll.stream()
            .distinct()
            .collect(toList());
        System.out.println("---得到去重并集 listAllDistinct---");
        listAllDistinct.parallelStream().forEachOrdered(System.out :: println);
 
        System.out.println("---原来的List1---");
        list1.parallelStream().forEachOrdered(System.out :: println);
        System.out.println("---原来的List2---");
        list2.parallelStream().forEachOrdered(System.out :: println);
 
    }
}

LocalDateTime🤔

全新的日期时间API。在JDK1.8之前,Java处理日期、日历和时间的方式一直为社区所诟病,将 java.util.Date 设定为可变类型,以及 SimpleDateFormat非线程安全使其应用非常受限。因此推出了java.time 包,该包下的所有类都是不可变类型而且线程安全

关键类

  • Instant:瞬时时间。

  • LocalDate:本地日期,不包含具体时间, 格式 yyyy-MM-dd

  • LocalTime:本地时间,不包含日期. 格式 yyyy-MM-dd HH:mm:ss.SSS

  • LocalDateTime:组合了日期和时间,但不包含时差和时区信息。

  • ZonedDateTime:最完整的日期时间,包含时区和相对UTC格林威治的时差。

获取当前的年月日时分秒

//获取当前的时间,包括毫秒 
LocalDateTime ldt = LocalDateTime.now();
System.out.println("当前年:"+ldt.getYear());  
System.out.println("当前年份天数:"+ldt.getDayOfYear());
System.out.println("当前月:"+ldt.getMonthValue());
System.out.println("当前时:"+ldt.getHour());
System.out.println("当前分:"+ldt.getMinute());
System.out.println("当前时间:"+ldt.toString());
// 输出
// 当前年:2022
// 当前年份天数:61
// 当前月:3
// 当前时:15
// 当前分:25
// 当前时间:2022-03-02T15:25:32.818

格式化时间

LocalDateTime ldt = LocalDateTime.now();
System.out.println("格式化时间: " +
 ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
// 格式化时间: 2022-03-02 15:25:32.818

时间增减

LocalDateTime ldt = LocalDateTime.now();
System.out.println("后5天时间:"+ldt.plusDays(5));
System.out.println("前5天时间并格式化:"
+ldt.minusDays(5).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); 
System.out.println("前一个月的时间:"
+ldt.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyyMM"))); 
System.out.println("后一个月的时间:"
+ldt.plusMonths(1)); 
System.out.println("指定2099年的当前时间:"+ldt.withYear(2099)); 
//输出
// 后5天时间:2022-03-07T15:25:32.818
// 前5天时间并格式化:2022-02-25
// 前一个月的时间:202202
// 后一个月的时间:2022-04-02T15:25:32.818
// 指定2099年的当前时间:2099-03-02T15:25:32.818

创建指定时间

LocalDate ld3=LocalDate.of(2019, Month.NOVEMBER, 17);
LocalDate ld4=LocalDate.of(2022, 02, 11);
System.out.println(ld3);
System.out.println(ld4);
// 输出
// 2019-11-17
// 2022-02-11

时间相差比较

// 示例一: 具体相差的年月日
LocalDate ld=LocalDate.parse("2021-11-17");
LocalDate ld2=LocalDate.parse("2022-01-05");
Period p=Period.between(ld, ld2);
System.out.println("相差年: "+p.getYears()+
" 相差月 :"+p.getMonths() +
" 相差天:"+p.getDays());
// 相差年: 0 相差月 :1 相差天:19
// 注:这里的月份是不满足一年,天数是不满足一个月的。这里实际相差的是1月19天,也就是49天。

// 示例二:相差总数的时间
LocalDate startDate = LocalDate.of(2021, 11, 17);
LocalDate endDate = LocalDate.of(2022, 01, 05);
System.out.println("相差月份:"+ChronoUnit.MONTHS.between(startDate, endDate));
System.out.println("两月之间的相差的天数   : " + 
ChronoUnit.DAYS.between(startDate, endDate));
// 相差月份:1
// 两月之间的相差的天数   : 49
// 注:ChronoUnit也可以计算相差时分秒。 


// 示例三:精度时间相差
// Duration 这个类以秒和纳秒为单位建模时间的数量或数量。
Instant inst1 = Instant.now();
System.out.println("当前时间戳 : " + inst1);
Instant inst2 = inst1.plus(Duration.ofSeconds(10));
System.out.println("增加之后的时间 : " + inst2);
System.out.println("相差毫秒 : " + Duration.between(inst1, inst2).toMillis());
System.out.println("相毫秒 : " + Duration.between(inst1, inst2).getSeconds());
// 输出
// 当前时间戳 : 2022-03-02T07:30:35.261Z
// 增加之后的时间 : 2022-03-02T07:30:45.261Z
// 相差毫秒 : 10000
// 相毫秒 : 10


// 示例四:时间大小比较
LocalDateTime ldt4 = LocalDateTime.now();
LocalDateTime ldt5 = ldt4.plusMinutes(10);
System.out.println("当前时间是否大于:"+ldt4.isAfter(ldt5));
System.out.println("当前时间是否小于"+ldt4.isBefore(ldt5));
// 当前时间是否大于:false
// 当前时间是否小于true

时区时间计算

// 示例一:通过Clock时钟类获取计算
// Clock时钟类用于获取当时的时间戳,或当前时区下的日期时间信息。

Clock clock = Clock.systemUTC();
System.out.println("当前时间戳 : " + clock.millis()); 
Clock clock2 = Clock.system(ZoneId.of("Asia/Shanghai"));
System.out.println("亚洲上海此时的时间戳:"+clock2.millis());
Clock clock3 = Clock.system(ZoneId.of("America/New_York"));
System.out.println("美国纽约此时的时间戳:"+clock3.millis());
// 当前时间戳 : 1646206235265
// 亚洲上海此时的时间戳:1646206235265
// 美国纽约此时的时间戳:1646206235266

// 示例二:通过ZonedDateTime类和ZoneId
ZoneId zoneId= ZoneId.of("America/New_York");
ZonedDateTime dateTime=ZonedDateTime.now(zoneId);
System.out.println("美国纽约此时的时间 : " + 
dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
System.out.println("美国纽约此时的时间 和时区: " + dateTime);
// 输出
// 美国纽约此时的时间 : 2022-03-02 02:30:35.266
// 美国纽约此时的时间 和时区: 2022-03-02T02:30:35.266-05:00[America/New_York]

一些代码合集

去重且属性值相加

  • 1、根据某个属性去重并相同属性的其他属性值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Data> dataList = new ArrayList<>();

        // 添加一些测试数据
        dataList.add(new Data("A", 10));
        dataList.add(new Data("B", 20));
        dataList.add(new Data("A", 30));
        dataList.add(new Data("C", 40));
        dataList.add(new Data("B", 50));

        // 根据属性值去重,并将另一个属性值相加
        List<Data> distinctList = dataList.stream()
                .collect(Collectors.toMap(Data::getProperty, // 根据属性值作为key
                        data -> data, // 保留原始对象
                        (data1, data2) -> new Data(data1.getProperty(), data1.getValue() + data2.getValue()))) // 相同属性值的其他属性值相加
                .values().stream()
                .collect(Collectors.toList());

        // 打印结果
        for (Data data : distinctList) {
            System.out.println(data.getProperty() + " - " + data.getValue());
        }
    }
}

class Data {
    private String property;
    private int value;

    public Data(String property, int value) {
        this.property = property;
        this.value = value;
    }

    public String getProperty() {
        return property;
    }

    public int getValue() {
        return value;
    }
}

  • 2、根据某个属性去重并根据相同属性将多个属性的值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Data> dataList = new ArrayList<>();

        // 添加一些测试数据
        dataList.add(new Data("A", 10, 1));
        dataList.add(new Data("B", 20, 2));
        dataList.add(new Data("A", 30, 3));
        dataList.add(new Data("C", 40, 4));
        dataList.add(new Data("B", 50, 5));

        // 根据属性值去重,并根据相同属性将多个属性的值相加
        List<Data> distinctList = dataList.stream()
                .collect(Collectors.toMap(Data::getProperty, // 根据属性值作为key
                        data -> data, // 保留原始对象
                        (data1, data2) -> {
                            data1.setValue1(data1.getValue1() + data2.getValue1()); // 将属性1相加
                            data1.setValue2(data1.getValue2() + data2.getValue2()); // 将属性2相加
                            return data1;
                        }))
                .values().stream()
                .collect(Collectors.toList());

        // 打印结果
        for (Data data : distinctList) {
            System.out.println(data.getProperty() + " - " + data.getValue1() + " - " + data.getValue2());
        }
    }
}

class Data {
    private String property;
    private int value1;
    private int value2;

    public Data(String property, int value1, int value2) {
        this.property = property;
        this.value1 = value1;
        this.value2 = value2;
    }

    public String getProperty() {
        return property;
    }

    public int getValue1() {
        return value1;
    }

    public void setValue1(int value1) {
        this.value1 = value1;
    }

    public int getValue2() {
        return value2;
    }

    public void setValue2(int value2) {
        this.value2 = value2;
    }
}

  • 3、根据多个属性去重并根据相同属性将多个属性的值相加,最终得到去重后的数据
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Data> dataList = new ArrayList<>();

        // 添加一些测试数据
        dataList.add(new Data("A", "X", 10));
        dataList.add(new Data("B", "Y", 20));
        dataList.add(new Data("A", "X", 30));
        dataList.add(new Data("C", "Z", 40));
        dataList.add(new Data("B", "Y", 50));

        // 根据多个属性去重,并根据相同属性将多个属性的值相加
        List<Data> distinctList = new ArrayList<>(dataList.stream()
                .collect(Collectors.toMap(data -> new Key(data.getProperty1(), data.getProperty2()), // 根据多个属性作为key
                        data -> data, // 保留原始对象
                        (data1, data2) -> {
                            data1.setValue(data1.getValue() + data2.getValue()); // 将属性值相加
                            return data1;
                        }))
                .values());

        // 打印结果
        for (Data data : distinctList) {
            System.out.println(data.getProperty1() + " - " + data.getProperty2() + " - " + data.getValue());
        }
    }
}

class Data {
    private String property1;
    private String property2;
    private int value;

    public Data(String property1, String property2, int value) {
        this.property1 = property1;
        this.property2 = property2;
        this.value = value;
    }

    public String getProperty1() {
        return property1;
    }

    public String getProperty2() {
        return property2;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }
}

class Key {
    private String property1;
    private String property2;

    public Key(String property1, String property2) {
        this.property1 = property1;
        this.property2 = property2;
    }

    @Override
    public int hashCode() {
        return property1.hashCode() + property2.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Key key = (Key) obj;
        return property1.equals(key.property1) && property2.equals(key.property2);
    }
}

Last Updated 2024/5/24 16:21:58