跳到主要内容

2024-07-24

一言

你必须要变强,才可以守护身边的人! --- 《坎公骑冠剑》 · 飞小RAN


YearMonth and LocalDate

在Java中,可以使用YearMonth类将其转换为LocalDateYearMonth表示特定年份和月份的组合,而LocalDate则表示具体的日期,包括年、月和日。因此,在转换时,需要指定一个具体的日。例如,可以选择月份的第一天或者最后一天。

下面是一些示例代码,展示了如何将YearMonth转换为LocalDate

将YearMonth转换为某个月的第一天

import java.time.YearMonth;
import java.time.LocalDate;

public class Main {
public static void main(String[] args) {
YearMonth yearMonth = YearMonth.of(2023, 7); // 2023年7月
LocalDate firstDayOfMonth = yearMonth.atDay(1); // 该月的第一天

System.out.println("YearMonth: " + yearMonth);
System.out.println("First day of month: " + firstDayOfMonth);
}
}

将YearMonth转换为某个月的最后一天

import java.time.YearMonth;
import java.time.LocalDate;

public class Main {
public static void main(String[] args) {
YearMonth yearMonth = YearMonth.of(2023, 7); // 2023年7月
LocalDate lastDayOfMonth = yearMonth.atEndOfMonth(); // 该月的最后一天

System.out.println("YearMonth: " + yearMonth);
System.out.println("Last day of month: " + lastDayOfMonth);
}
}

通过以上方法,可以根据需要将YearMonth转换为LocalDate,并且可以选择月份中的具体日期。

在Java中,可以通过LocalDate类的getYear()getMonth()方法,使用YearMonth.of(int year, Month month)LocalDate转换为YearMonth。以下是具体的示例代码:

import java.time.LocalDate;
import java.time.YearMonth;

public class Main {
public static void main(String[] args) {
LocalDate localDate = LocalDate.of(2023, 7, 23); // 2023年7月23日

// 将LocalDate转换为YearMonth
YearMonth yearMonth = YearMonth.of(localDate.getYear(), localDate.getMonth());

System.out.println("LocalDate: " + localDate);
System.out.println("YearMonth: " + yearMonth);
}
}

代码解析

  1. LocalDate.of(2023, 7, 23):创建一个特定日期的LocalDate对象。
  2. localDate.getYear():获取LocalDate对象的年份。
  3. localDate.getMonth():获取LocalDate对象的月份。
  4. YearMonth.of(localDate.getYear(), localDate.getMonth()):使用年份和月份创建YearMonth对象。

通过这种方式,可以将LocalDate转换为YearMonth,并且只保留日期中的年和月信息。

在Java中,YearMonth类实现了Comparable<YearMonth>接口,因此可以直接使用compareTo方法来比较两个YearMonth对象的大小。此外,还可以使用isBeforeisAfter方法来进行比较。

以下是一些示例代码,展示了如何使用这些方法比较两个YearMonth对象:

使用compareTo方法

import java.time.YearMonth;

public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // 2023年7月
YearMonth ym2 = YearMonth.of(2024, 3); // 2024年3月

int comparison = ym1.compareTo(ym2);

if (comparison < 0) {
System.out.println(ym1 + " is before " + ym2);
} else if (comparison > 0) {
System.out.println(ym1 + " is after " + ym2);
} else {
System.out.println(ym1 + " is equal to " + ym2);
}
}
}

使用isBefore方法

import java.time.YearMonth;

public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // 2023年7月
YearMonth ym2 = YearMonth.of(2024, 3); // 2024年3月

if (ym1.isBefore(ym2)) {
System.out.println(ym1 + " is before " + ym2);
} else if (ym1.isAfter(ym2)) {
System.out.println(ym1 + " is after " + ym2);
} else {
System.out.println(ym1 + " is equal to " + ym2);
}
}
}

使用isAfter方法

import java.time.YearMonth;

public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // 2023年7月
YearMonth ym2 = YearMonth.of(2024, 3); // 2024年3月

if (ym1.isAfter(ym2)) {
System.out.println(ym1 + " is after " + ym2);
} else if (ym1.isBefore(ym2)) {
System.out.println(ym1 + " is before " + ym2);
} else {
System.out.println(ym1 + " is equal to " + ym2);
}
}
}

通过以上方法,可以方便地比较两个YearMonth对象的大小,从而确定它们之间的先后顺序。

在Java中,YearMonth类提供了便捷的方法来计算两个YearMonth对象之间的差值。可以使用until方法来计算两个YearMonth之间的年数和月数差值。until方法返回一个Period对象,表示这两个YearMonth对象之间的时间差。

以下是一些示例代码,展示了如何计算两个YearMonth对象之间的差值:

计算两个YearMonth对象之间的差值(以年和月为单位)

import java.time.YearMonth;
import java.time.Period;

public class Main {
public static void main(String[] args) {
YearMonth start = YearMonth.of(2023, 7); // 2023年7月
YearMonth end = YearMonth.of(2024, 3); // 2024年3月

// 计算两个YearMonth之间的差值
Period period = start.until(end);

int years = period.getYears();
int months = period.getMonths();

System.out.println("差值: " + years + " 年 " + months + " 月");
}
}

计算两个YearMonth对象之间的总月数差值

import java.time.YearMonth;

public class Main {
public static void main(String[] args) {
YearMonth start = YearMonth.of(2023, 7); // 2023年7月
YearMonth end = YearMonth.of(2024, 3); // 2024年3月

// 计算两个YearMonth之间的总月数差值
int totalMonths = start.until(end, java.time.temporal.ChronoUnit.MONTHS);

System.out.println("总月数差值: " + totalMonths + " 月");
}
}

代码解析

  1. start.until(end):计算两个YearMonth之间的差值,并返回一个Period对象。
  2. period.getYears():获取年数差值。
  3. period.getMonths():获取月数差值。
  4. start.until(end, java.time.temporal.ChronoUnit.MONTHS):计算两个YearMonth之间的总月数差值。

通过上述方法,可以轻松地计算两个YearMonth对象之间的年数和月数差值,以及总月数差值。

带有负载因子的集合

今天发现了我对于集合理解的一个误区

在Java集合框架中,负载因子(load factor)是一个影响集合扩容行为的重要参数。负载因子主要应用于基于哈希表的数据结构。以下是一些主要使用负载因子的集合:

1. HashMap

  • 默认负载因子:0.75
  • 用途:用于控制哈希表何时需要调整大小。当元素数量超过容量与负载因子的乘积时,触发扩容。
Map<Integer, String> map = new HashMap<>();

2. LinkedHashMap

  • 默认负载因子:0.75
  • 用途:与HashMap类似,但维护插入顺序或访问顺序。负载因子的使用与HashMap相同。
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();

3. Hashtable

  • 默认负载因子:0.75
  • 用途:一个线程安全的哈希表实现,使用负载因子来控制扩容。
Map<Integer, String> hashtable = new Hashtable<>();

4. ConcurrentHashMap

  • 默认负载因子:0.75
  • 用途:用于并发环境下的哈希表实现。负载因子用于控制哈希表何时需要扩容。
Map<Integer, String> concurrentHashMap = new ConcurrentHashMap<>();

5. HashSet

  • 默认负载因子:0.75
  • 用途HashSet内部使用HashMap实现,因此负载因子的使用与HashMap相同。
Set<Integer> hashSet = new HashSet<>();

6. LinkedHashSet

  • 默认负载因子:0.75
  • 用途LinkedHashSet内部使用LinkedHashMap实现,因此负载因子的使用与LinkedHashMap相同。
Set<Integer> linkedHashSet = new LinkedHashSet<>();

自定义负载因子

在这些集合中,可以通过构造函数来指定自定义的初始容量和负载因子。例如:

Map<Integer, String> map = new HashMap<>(16, 0.75f);
Set<Integer> set = new HashSet<>(16, 0.75f);

总结

在Java集合框架中,主要基于哈希表实现的数据结构(如HashMapLinkedHashMapHashtableConcurrentHashMapHashSetLinkedHashSet)都使用负载因子来控制扩容行为。负载因子是一个影响这些集合性能的重要参数,默认值通常为0.75,表示当元素数量达到容量的75%时,集合会进行扩容。

Stream.reduce

Stream.reduce方法在Java Stream API中是一个强大的终端操作,用于将流中的元素组合成一个单一的结果。它通过指定的累加器函数(以及可选的初始值)将流中的元素逐个处理,最终生成一个结果。reduce方法提供了三种重载形式。

三种重载形式

  1. 单参数重载形式

    • Optional<T> reduce(BinaryOperator<T> accumulator)
    • 该形式使用一个累加器函数,返回一个Optional值。返回值是流中所有元素使用累加器函数计算后的结果,如果流为空,则返回Optional.empty()
  2. 双参数重载形式

    • <U> U reduce(U identity, BinaryOperator<U> accumulator)
    • 该形式使用一个初始值(identity)和一个累加器函数,返回累加的结果。如果流为空,返回初始值。
  3. 三参数重载形式

    • <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
    • 该形式适用于并行流。使用初始值、累加器函数和合并函数。累加器函数将元素累加到结果中,合并函数将并行计算的结果合并在一起。

示例代码

以下是每种重载形式的示例代码:

1. 单参数重载形式

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);

sum.ifPresent(System.out::println); // 输出: 15
}
}

2. 双参数重载形式

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

Integer sum = numbers.stream().reduce(0, (a, b) -> a + b);

System.out.println(sum); // 输出: 15
}
}

3. 三参数重载形式

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

Integer sum = numbers.parallelStream().reduce(0,
(a, b) -> a + b,
(a, b) -> a + b);

System.out.println(sum); // 输出: 15
}
}

参数解释

  • identity:一个初始值,这个值是累加器函数的第一个参数,也是最终返回结果的默认值(在流为空时返回)。
  • accumulator:一个函数,用于将流中的元素组合起来。它接受两个参数:第一个参数是累加结果,第二个参数是流中的元素,返回新的累加结果。
  • combiner:一个函数,用于在并行流中合并部分结果。只有在使用并行流时才需要提供这个参数。

使用示例

示例1:计算流中所有整数的乘积

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

Integer product = numbers.stream().reduce(1, (a, b) -> a * b);

System.out.println(product); // 输出: 120
}
}

示例2:计算流中所有字符串的连接

import java.util.Arrays;
import java.util.List;

public class ReduceExample {
public static void main(String[] args) {
List<String> words = Arrays.asList("Hello", "world", "Java", "Stream");

String concatenated = words.stream().reduce("", (a, b) -> a + " " + b);

System.out.println(concatenated.trim()); // 输出: "Hello world Java Stream"
}
}

总结

Stream.reduce方法是一个强大的工具,可以用于各种场景中将流中的元素组合成一个结果。它支持串行和并行计算,通过不同的重载形式提供了灵活的使用方式。了解和掌握reduce方法的使用,对于熟练使用Java Stream API非常重要。