2024-07-24
You must become stronger to protect the people around you! --- Guardian Tales · Fei XiaoRAN
YearMonth and LocalDate in Java
In Java, you can convert a YearMonth
to a LocalDate
. YearMonth
represents a specific combination of a year and month, while LocalDate
represents a complete date including year, month, and day. Therefore, when converting, you need to specify a specific day, such as the first or last day of the month.
Here are some examples showing how to convert YearMonth
to LocalDate
:
Converting YearMonth to the First Day of the Month
import java.time.YearMonth;
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
YearMonth yearMonth = YearMonth.of(2023, 7); // July 2023
LocalDate firstDayOfMonth = yearMonth.atDay(1); // First day of the month
System.out.println("YearMonth: " + yearMonth);
System.out.println("First day of month: " + firstDayOfMonth);
}
}
Converting YearMonth to the Last Day of the Month
import java.time.YearMonth;
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
YearMonth yearMonth = YearMonth.of(2023, 7); // July 2023
LocalDate lastDayOfMonth = yearMonth.atEndOfMonth(); // Last day of the month
System.out.println("YearMonth: " + yearMonth);
System.out.println("Last day of month: " + lastDayOfMonth);
}
}
By using the above methods, you can convert a YearMonth
to a LocalDate
and choose a specific day of the month.
Converting LocalDate to YearMonth
In Java, you can use the getYear()
and getMonth()
methods of the LocalDate
class to convert a LocalDate
to a YearMonth
using YearMonth.of(int year, Month month)
. Here is a concrete example:
import java.time.LocalDate;
import java.time.YearMonth;
public class Main {
public static void main(String[] args) {
LocalDate localDate = LocalDate.of(2023, 7, 23); // July 23, 2023
// Convert LocalDate to YearMonth
YearMonth yearMonth = YearMonth.of(localDate.getYear(), localDate.getMonth());
System.out.println("LocalDate: " + localDate);
System.out.println("YearMonth: " + yearMonth);
}
}
Code Explanation
LocalDate.of(2023, 7, 23)
: Creates aLocalDate
object for a specific date.localDate.getYear()
: Gets the year from theLocalDate
object.localDate.getMonth()
: Gets the month from theLocalDate
object.YearMonth.of(localDate.getYear(), localDate.getMonth())
: Creates aYearMonth
object using the year and month.
By this method, you can convert a LocalDate
to a YearMonth
, retaining only the year and month information from the date.
Comparing YearMonth Objects
In Java, the YearMonth
class implements the Comparable<YearMonth>
interface, so you can directly use the compareTo
method to compare two YearMonth
objects. You can also use the isBefore
and isAfter
methods for comparison.
Here are some examples demonstrating how to use these methods to compare YearMonth
objects:
Using compareTo
Method
import java.time.YearMonth;
public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // July 2023
YearMonth ym2 = YearMonth.of(2024, 3); // March 2024
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);
}
}
}
Using isBefore
Method
import java.time.YearMonth;
public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // July 2023
YearMonth ym2 = YearMonth.of(2024, 3); // March 2024
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);
}
}
}
Using isAfter
Method
import java.time.YearMonth;
public class Main {
public static void main(String[] args) {
YearMonth ym1 = YearMonth.of(2023, 7); // July 2023
YearMonth ym2 = YearMonth.of(2024, 3); // March 2024
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);
}
}
}
These methods make it convenient to compare YearMonth
objects and determine their relative order.
Calculating the Difference Between Two YearMonth Objects
In Java, the YearMonth
class provides convenient methods to calculate the difference between two YearMonth
objects. You can use the until
method to calculate the difference in years and months. The until
method returns a Period
object representing the time difference between the two YearMonth
objects.
Here are some examples demonstrating how to calculate the difference between two YearMonth
objects:
Calculating the Difference in Years and Months
import java.time.YearMonth;
import java.time.Period;
public class Main {
public static void main(String[] args) {
YearMonth start = YearMonth.of(2023, 7); // July 2023
YearMonth end = YearMonth.of(2024, 3); // March 2024
// Calculate the difference between the two YearMonth objects
Period period = start.until(end);
int years = period.getYears();
int months = period.getMonths();
System.out.println("Difference: " + years + " years " + months + " months");
}
}
Calculating the Total Difference in Months
import java.time.YearMonth;
public class Main {
public static void main(String[] args) {
YearMonth start = YearMonth.of(2023, 7); // July 2023
YearMonth end = YearMonth.of(2024, 3); // March 2024
// Calculate the total difference in months between the two YearMonth objects
int totalMonths = start.until(end, java.time.temporal.ChronoUnit.MONTHS);
System.out.println("Total difference: " + totalMonths + " months");
}
}
Code Explanation
start.until(end)
: Calculates the difference between the twoYearMonth
objects and returns aPeriod
object.period.getYears()
: Gets the difference in years.period.getMonths()
: Gets the difference in months.start.until(end, java.time.temporal.ChronoUnit.MONTHS)
: Calculates the total difference in months between the twoYearMonth
objects.
By using the above methods, you can easily calculate the difference in years and months between two YearMonth
objects as well as the total difference in months.
Load Factor in Java Collections
In the Java Collections Framework, the load factor is an important parameter that influences the resizing behavior of collections. The load factor mainly applies to data structures based on hash tables. Here are some collections that use load factors:
1. HashMap
- Default Load Factor: 0.75
- Purpose: Controls when the hash table needs to resize. When the number of elements exceeds the product of the capacity and load factor, resizing is triggered.
Map<Integer, String> map = new HashMap<>();
2. LinkedHashMap
- Default Load Factor: 0.75
- Purpose: Similar to
HashMap
but maintains insertion order or access order. The load factor usage is the same as inHashMap
.
Map<Integer, String> linkedHashMap = new LinkedHashMap<>();
3. Hashtable
- Default Load Factor: 0.75
- Purpose: A thread-safe implementation of a hash table that uses a load factor to control resizing.
Map<Integer, String> hashtable = new Hashtable<>();
4. ConcurrentHashMap
- Default Load Factor: 0.75
- Purpose: A hash table implementation for concurrent environments. The load factor is used to control when the hash table needs to resize.
Map<Integer, String> concurrentHashMap = new ConcurrentHashMap<>();
5. HashSet
- Default Load Factor: 0.75
- Purpose: Internally uses a
HashMap
, so the load factor usage is the same as inHashMap
.
Set<Integer> hashSet = new HashSet<>();
6. LinkedHashSet
- Default Load Factor: 0.75
- Purpose: Internally uses a
LinkedHashMap
, so the load factor usage is the same as inLinkedHashMap
.
Set<Integer> linkedHashSet = new LinkedHashSet<>();
Custom Load Factor
In these collections, you can specify a custom initial capacity and load factor through the constructor. For example:
Map<Integer, String> map = new HashMap<>(16, 0.75f);
Set<Integer> set = new HashSet<>(16, 0.75f);
Summary
In the Java Collections Framework, data structures mainly based on hash tables (such as HashMap
, LinkedHashMap
, Hashtable
, ConcurrentHashMap
, HashSet
, and LinkedHashSet
) use load factors to control resizing behavior. The load factor is an important parameter that influences the performance of these collections, with a default value typically set to 0.75, meaning that the collection will resize when the number of elements reaches 75% of the capacity.
Stream.reduce Method
The Stream.reduce
method in the Java Stream API is a powerful terminal operation used to combine elements of a stream into a single result. It processes the elements of the stream using a specified accumulator function (and an optional initial value) to produce a final result. The reduce
method has three overloaded forms.
Three Overloaded Forms
-
Single-parameter overloaded form:
Optional<T> reduce(BinaryOperator<T> accumulator)
- This form uses an accumulator function and returns an
Optional
value. The return value is the result of combining all elements of the stream using the accumulator function. If the stream is empty, it returnsOptional.empty()
.
-
Two-parameter overloaded form:
<U> U reduce(U identity, BinaryOperator<U> accumulator)
- This form uses an initial value (identity) and an accumulator function, and returns the accumulated result. If the stream is empty, it returns the initial value.
-
Three-parameter overloaded form:
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
- This form is suitable for parallel streams. It uses an initial value, an accumulator function, and a combiner function. The accumulator function accumulates elements into the result, and the combiner function combines the partial results of parallel computations.
Example Code
Here is example code for each overloaded form:
1. Single-parameter overloaded form
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); // Output: 15
}
}
2. Two-parameter overloaded form
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); // Output: 15
}
}
3. Three-parameter overloaded form
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); // Output: 15
}
}
Parameter Explanation
- identity: An initial value that is the first argument to the accumulator function and is also the default return value if the stream is empty.
- accumulator: A function that combines elements of the stream. It takes two parameters: the first is the accumulated result, and the second is the stream element, returning a new accumulated result.
- combiner: A function that combines partial results in parallel streams. This parameter is needed only when using parallel streams.
Usage Examples
Example 1: Calculating the Product of All Integers in a Stream
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); // Output: 120
}
}
Example 2: Concatenating All Strings in a Stream
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()); // Output: "Hello world Java Stream"
}
}
Summary
The Stream.reduce
method is a powerful tool that can be used in various scenarios to combine elements of a stream into a single result. It supports both sequential and parallel computations and provides flexible usage through different overloaded forms. Understanding and mastering the use of the reduce
method is essential for proficient use of the Java Stream API.