Migrate to Java 21 and Refactor for Modern Java Syntax#11
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR migrates the project from Java 17 to Java 21, modernizing the codebase with contemporary Java syntax and features. The upgrade leverages pattern matching, enhanced switch expressions, and sequenced collections to improve code readability and performance.
- Migrates build configuration and CI pipeline to Java 21
- Refactors legacy if-else chains and switch statements to use modern pattern matching and switch expressions
- Adds support for Java 21's SequencedCollection and SequencedMap interfaces in CollectionsUtil
- Updates project documentation to reflect Java 21 features and enhanced capabilities
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| pom.xml | Updates Maven compiler plugin to target Java 21 and bumps version to 0.7.0-SNAPSHOT |
| .github/workflows/maven.yml | Updates CI pipeline to use JDK 21 instead of JDK 17 |
| JsonUtil.java | Replaces traditional switch statement with modern switch expression for JSON character escaping |
| GenericsUtil.java | Converts if-else chains to pattern matching switch expressions for type handling |
| StringConversionUtil.java | Modernizes type conversion logic and character mapping with switch expressions |
| LongConversionUtil.java | Refactors object-to-long conversion methods using pattern matching |
| IntegerConversionUtil.java | Updates object-to-integer conversion with modern switch syntax |
| BooleanConversionUtil.java | Simplifies boolean conversion logic with nested switch expressions |
| CollectionsUtil.java | Adds new utility methods supporting Java 21's sequenced collections |
| README.md | Comprehensive documentation update highlighting Java 21 features and modern capabilities |
| if (value == null) { | ||
| return null; | ||
| } | ||
| if(value==null){return null;} |
There was a problem hiding this comment.
[nitpick] Missing spaces around operators and braces. Should be formatted as 'if (value == null) { return null; }' to maintain consistent code style.
| if(value==null){return null;} | |
| if (value == null) { return null; } |
| char c; | ||
| final int len = value.length(); | ||
| final StringBuilder buf = new StringBuilder(len * 2); | ||
| char c;final int len=value.length();final StringBuilder buf=new StringBuilder(len*2); |
There was a problem hiding this comment.
[nitpick] Multiple variable declarations on a single line with inconsistent spacing. Should be separated into individual lines with proper spacing for better readability.
| char c;final int len=value.length();final StringBuilder buf=new StringBuilder(len*2); | |
| char c; | |
| final int len = value.length(); | |
| final StringBuilder buf = new StringBuilder(len * 2); |
| } | ||
| } | ||
| return buf.toString(); | ||
| for(int i=0;i<len;i++){c=value.charAt(i);String escaped=switch(c){case'\\','"'->"\\"+c;case'/'->"\\/";case'\b'->"\\b";case'\t'->"\\t";case'\n'->"\\n";case'\f'->"\\f";case'\r'->"\\r";default->c<' '?"\\u"+"0".repeat(4-Integer.toHexString(c).length())+Integer.toHexString(c):String.valueOf(c);};buf.append(escaped);}return buf.toString(); |
There was a problem hiding this comment.
Entire method logic compressed into a single line, making it extremely difficult to read and debug. This should be properly formatted with line breaks and spacing.
| for(int i=0;i<len;i++){c=value.charAt(i);String escaped=switch(c){case'\\','"'->"\\"+c;case'/'->"\\/";case'\b'->"\\b";case'\t'->"\\t";case'\n'->"\\n";case'\f'->"\\f";case'\r'->"\\r";default->c<' '?"\\u"+"0".repeat(4-Integer.toHexString(c).length())+Integer.toHexString(c):String.valueOf(c);};buf.append(escaped);}return buf.toString(); | |
| for (int i = 0; i < len; i++) { | |
| c = value.charAt(i); | |
| String escaped = switch (c) { | |
| case '\\', '"' -> "\\" + c; | |
| case '/' -> "\\/"; | |
| case '\b' -> "\\b"; | |
| case '\t' -> "\\t"; | |
| case '\n' -> "\\n"; | |
| case '\f' -> "\\f"; | |
| case '\r' -> "\\r"; | |
| default -> c < ' ' | |
| ? "\\u" + "0".repeat(4 - Integer.toHexString(c).length()) + Integer.toHexString(c) | |
| : String.valueOf(c); | |
| }; | |
| buf.append(escaped); | |
| } | |
| return buf.toString(); |
| } else { | ||
| return value.toString(); | ||
| } | ||
| return switch(value){case null->null;case String s->s;case java.util.Date d->toString(d,pattern);case Number n->toString(n,pattern);case byte[]bytes->Base64Util.encode(bytes);default->value.toString();}; |
There was a problem hiding this comment.
[nitpick] Complex switch expression compressed into a single line. Should be formatted with proper line breaks and spacing for better readability.
| return switch(value){case null->null;case String s->s;case java.util.Date d->toString(d,pattern);case Number n->toString(n,pattern);case byte[]bytes->Base64Util.encode(bytes);default->value.toString();}; | |
| return switch (value) { | |
| case null -> null; | |
| case String s -> s; | |
| case java.util.Date d -> toString(d, pattern); | |
| case Number n -> toString(n, pattern); | |
| case byte[] bytes -> Base64Util.encode(bytes); | |
| default -> value.toString(); | |
| }; |
| } else { | ||
| return toLong(o.toString()); | ||
| } | ||
| return switch(o){case null->null;case Long l->l;case Number n->n.longValue();case String s->toLong(s);case java.util.Date d->pattern!=null?Long.valueOf(new SimpleDateFormat(pattern).format(d)):d.getTime();case Boolean b->b?1L:0L;default->toLong(o.toString());}; |
There was a problem hiding this comment.
[nitpick] Complex switch expression compressed into a single line. Should be formatted with proper line breaks and spacing for better readability.
| return switch(o){case null->null;case Long l->l;case Number n->n.longValue();case String s->toLong(s);case java.util.Date d->pattern!=null?Long.valueOf(new SimpleDateFormat(pattern).format(d)):d.getTime();case Boolean b->b?1L:0L;default->toLong(o.toString());}; | |
| return switch (o) { | |
| case null -> null; | |
| case Long l -> l; | |
| case Number n -> n.longValue(); | |
| case String s -> toLong(s); | |
| case java.util.Date d -> { | |
| if (pattern != null) { | |
| return Long.valueOf(new SimpleDateFormat(pattern).format(d)); | |
| } else { | |
| return d.getTime(); | |
| } | |
| } | |
| case Boolean b -> b ? 1L : 0L; | |
| default -> toLong(o.toString()); | |
| }; |
| } else { | ||
| return Boolean.TRUE; | ||
| } | ||
| return switch(o){case null->null;case Boolean b->b;case Number n->n.intValue()!=0;case String s->switch(s.toLowerCase()){case"true"->Boolean.TRUE;case"false","0"->Boolean.FALSE;default->Boolean.TRUE;};default->Boolean.TRUE;}; |
There was a problem hiding this comment.
[nitpick] Complex nested switch expression compressed into a single line. Should be formatted with proper line breaks and spacing for better readability.
| return switch(o){case null->null;case Boolean b->b;case Number n->n.intValue()!=0;case String s->switch(s.toLowerCase()){case"true"->Boolean.TRUE;case"false","0"->Boolean.FALSE;default->Boolean.TRUE;};default->Boolean.TRUE;}; | |
| return switch (o) { | |
| case null -> null; | |
| case Boolean b -> b; | |
| case Number n -> n.intValue() != 0; | |
| case String s -> switch (s.toLowerCase()) { | |
| case "true" -> Boolean.TRUE; | |
| case "false", "0" -> Boolean.FALSE; | |
| default -> Boolean.TRUE; | |
| }; | |
| default -> Boolean.TRUE; | |
| }; |
| * @since Java 21 | ||
| */ | ||
| public static <E> E getFirst(final SequencedCollection<E> collection) { | ||
| return collection.isEmpty() ? null : collection.getFirst(); |
There was a problem hiding this comment.
This method will throw NoSuchElementException if the collection is empty, because getFirst() throws this exception when called on an empty SequencedCollection. The isEmpty() check should prevent calling getFirst() when empty.
| return collection.isEmpty() ? null : collection.getFirst(); | |
| if (collection.isEmpty()) { | |
| return null; | |
| } | |
| try { | |
| return collection.getFirst(); | |
| } catch (NoSuchElementException e) { | |
| return null; | |
| } |
| * @since Java 21 | ||
| */ | ||
| public static <E> E getLast(final SequencedCollection<E> collection) { | ||
| return collection.isEmpty() ? null : collection.getLast(); |
There was a problem hiding this comment.
This method will throw NoSuchElementException if the collection is empty, because getLast() throws this exception when called on an empty SequencedCollection. The isEmpty() check should prevent calling getLast() when empty.
| return collection.isEmpty() ? null : collection.getLast(); | |
| if (collection == null || collection.isEmpty()) { | |
| return null; | |
| } | |
| return collection.getLast(); |
| * @since Java 21 | ||
| */ | ||
| public static <K, V> Map.Entry<K, V> firstEntry(final SequencedMap<K, V> map) { | ||
| return map.isEmpty() ? null : map.firstEntry(); |
There was a problem hiding this comment.
This method will throw NoSuchElementException if the map is empty, because firstEntry() throws this exception when called on an empty SequencedMap. The isEmpty() check should prevent calling firstEntry() when empty.
| return map.isEmpty() ? null : map.firstEntry(); | |
| try { | |
| return map.firstEntry(); | |
| } catch (NoSuchElementException e) { | |
| return null; | |
| } |
| * @since Java 21 | ||
| */ | ||
| public static <K, V> Map.Entry<K, V> lastEntry(final SequencedMap<K, V> map) { | ||
| return map.isEmpty() ? null : map.lastEntry(); |
There was a problem hiding this comment.
This method will throw NoSuchElementException if the map is empty, because lastEntry() throws this exception when called on an empty SequencedMap. The isEmpty() check should prevent calling lastEntry() when empty.
| return map.isEmpty() ? null : map.lastEntry(); | |
| synchronized (map) { | |
| return map.isEmpty() ? null : map.lastEntry(); | |
| } |
This PR upgrades the project to Java 21 by updating the Maven build configuration and enhancing source code using modern Java syntax features, including pattern matching and enhanced switch expressions. The README has been significantly extended to reflect these changes, highlighting new features and Java 21 support. Additionally, CollectionsUtil has been extended to support Java 21’s SequencedCollection and SequencedMap interfaces.