Skip to content

Commit 0c78f74

Browse files
authored
Merge pull request #19 from javaevolved/copilot/add-new-java-patterns
Add 6 Java patterns and fix resource leak in writing-files
2 parents 5fbbafb + e247d91 commit 0c78f74

12 files changed

+270
-6
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"id": 96,
3+
"slug": "reverse-list-iteration",
4+
"title": "Reverse list iteration",
5+
"category": "collections",
6+
"difficulty": "beginner",
7+
"jdkVersion": "21",
8+
"oldLabel": "Java 8",
9+
"modernLabel": "Java 21+",
10+
"oldApproach": "Manual ListIterator",
11+
"modernApproach": "reversed()",
12+
"oldCode": "for (ListIterator<String> it =\n list.listIterator(list.size());\n it.hasPrevious(); ) {\n String element = it.previous();\n System.out.println(element);\n}",
13+
"modernCode": "for (String element : list.reversed()) {\n System.out.println(element);\n}",
14+
"summary": "Iterate over a list in reverse order with a clean for-each loop.",
15+
"explanation": "The reversed() method from SequencedCollection returns a reverse-ordered view of the list. This view is backed by the original list, so no copying occurs. The enhanced for loop syntax makes reverse iteration as readable as forward iteration.",
16+
"whyModernWins": [
17+
{
18+
"icon": "📖",
19+
"title": "Natural syntax",
20+
"desc": "Enhanced for loop instead of verbose ListIterator."
21+
},
22+
{
23+
"icon": "",
24+
"title": "No copying",
25+
"desc": "reversed() returns a view — no performance overhead."
26+
},
27+
{
28+
"icon": "🧩",
29+
"title": "Consistent API",
30+
"desc": "Works on List, Deque, SortedSet uniformly."
31+
}
32+
],
33+
"support": {
34+
"state": "available",
35+
"description": "Widely available since JDK 21 LTS (Sept 2023)"
36+
},
37+
"prev": "collections/stream-toarray-typed",
38+
"next": "collections/unmodifiable-collectors",
39+
"related": [
40+
"collections/sequenced-collections",
41+
"collections/immutable-list-creation",
42+
"streams/stream-tolist"
43+
]
44+
}

content/collections/stream-toarray-typed.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"description": "Widely available since JDK 8 (March 2014)"
3636
},
3737
"prev": "collections/collectors-teeing",
38-
"next": "collections/unmodifiable-collectors",
38+
"next": "collections/reverse-list-iteration",
3939
"related": [
4040
"collections/collectors-teeing",
4141
"collections/map-entry-factory",

content/collections/unmodifiable-collectors.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"state": "available",
3535
"description": "Widely available since JDK 10 (March 2018)"
3636
},
37-
"prev": "collections/stream-toarray-typed",
37+
"prev": "collections/reverse-list-iteration",
3838
"next": "strings/string-isblank",
3939
"related": [
4040
"collections/immutable-map-creation",
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"id": 97,
3+
"slug": "file-memory-mapping",
4+
"title": "File memory mapping",
5+
"category": "io",
6+
"difficulty": "advanced",
7+
"jdkVersion": "22",
8+
"oldLabel": "Java 8",
9+
"modernLabel": "Java 22+",
10+
"oldApproach": "MappedByteBuffer",
11+
"modernApproach": "MemorySegment with Arena",
12+
"oldCode": "try (FileChannel channel =\n FileChannel.open(path,\n StandardOpenOption.READ,\n StandardOpenOption.WRITE)) {\n MappedByteBuffer buffer =\n channel.map(\n FileChannel.MapMode.READ_WRITE,\n 0, (int) channel.size());\n // Limited to 2GB\n // Freed by GC, no control\n}",
13+
"modernCode": "FileChannel channel =\n FileChannel.open(path,\n StandardOpenOption.READ,\n StandardOpenOption.WRITE);\ntry (Arena arena = Arena.ofShared()) {\n MemorySegment segment =\n channel.map(\n FileChannel.MapMode.READ_WRITE,\n 0, channel.size(), arena);\n // No size limit\n // ...\n} // Deterministic cleanup",
14+
"summary": "Map files larger than 2GB with deterministic cleanup using MemorySegment.",
15+
"explanation": "The Foreign Function & Memory API (JEP 454) introduces MemorySegment for safe and efficient memory access. Unlike MappedByteBuffer, MemorySegment supports files larger than 2GB (Integer.MAX_VALUE), provides deterministic cleanup via Arena, and offers better performance with modern hardware.",
16+
"whyModernWins": [
17+
{
18+
"icon": "📏",
19+
"title": "No size limit",
20+
"desc": "Map files larger than 2GB without workarounds."
21+
},
22+
{
23+
"icon": "🔒",
24+
"title": "Deterministic cleanup",
25+
"desc": "Arena ensures memory is freed at scope exit, not GC time."
26+
},
27+
{
28+
"icon": "",
29+
"title": "Better performance",
30+
"desc": "Aligned with modern memory models and hardware."
31+
}
32+
],
33+
"support": {
34+
"state": "available",
35+
"description": "Available since JDK 22 (March 2024)"
36+
},
37+
"prev": "io/try-with-resources-effectively-final",
38+
"next": "io/files-mismatch",
39+
"related": [
40+
"io/http-client",
41+
"io/reading-files",
42+
"io/writing-files"
43+
]
44+
}

content/io/files-mismatch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"state": "available",
3535
"description": "Widely available since JDK 12 (March 2019)"
3636
},
37-
"prev": "io/try-with-resources-effectively-final",
37+
"prev": "io/file-memory-mapping",
3838
"next": "io/deserialization-filters",
3939
"related": [
4040
"io/inputstream-transferto",

content/io/try-with-resources-effectively-final.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"description": "Widely available since JDK 9 (Sept 2017)"
3636
},
3737
"prev": "io/path-of",
38-
"next": "io/files-mismatch",
38+
"next": "io/file-memory-mapping",
3939
"related": [
4040
"io/path-of",
4141
"io/reading-files",

content/io/writing-files.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"modernLabel": "Java 11+",
1010
"oldApproach": "FileWriter + BufferedWriter",
1111
"modernApproach": "Files.writeString()",
12-
"oldCode": "try (BufferedWriter bw =\n new BufferedWriter(\n new FileWriter(\"out.txt\"))) {\n bw.write(content);\n}",
12+
"oldCode": "try (FileWriter fw =\n new FileWriter(\"out.txt\");\n BufferedWriter bw =\n new BufferedWriter(fw)) {\n bw.write(content);\n}",
1313
"modernCode": "Files.writeString(\n Path.of(\"out.txt\"),\n content\n);",
1414
"summary": "Write a String to a file with one line.",
1515
"explanation": "Files.writeString() writes content to a file with UTF-8 encoding by default. Options can be passed for appending, creating, etc.",
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"id": 95,
3+
"slug": "compact-canonical-constructor",
4+
"title": "Compact canonical constructor",
5+
"category": "language",
6+
"difficulty": "intermediate",
7+
"jdkVersion": "16",
8+
"oldLabel": "Java 16",
9+
"modernLabel": "Java 16+",
10+
"oldApproach": "Explicit constructor validation",
11+
"modernApproach": "Compact constructor",
12+
"oldCode": "public record Person(String name,\n List<String> pets) {\n // Full canonical constructor\n public Person(String name,\n List<String> pets) {\n Objects.requireNonNull(name);\n this.name = name;\n this.pets = List.copyOf(pets);\n }\n}",
13+
"modernCode": "public record Person(String name,\n List<String> pets) {\n // Compact constructor\n public Person {\n Objects.requireNonNull(name);\n pets = List.copyOf(pets);\n }\n}",
14+
"summary": "Validate and normalize record fields without repeating parameter lists.",
15+
"explanation": "Records can declare a compact canonical constructor that omits the parameter list and field assignments. The compiler automatically assigns parameters to fields after your validation logic runs. This is ideal for precondition checks, defensive copies, and normalization.",
16+
"whyModernWins": [
17+
{
18+
"icon": "✂️",
19+
"title": "Less repetition",
20+
"desc": "No need to repeat parameter list or assign each field manually."
21+
},
22+
{
23+
"icon": "🛡️",
24+
"title": "Validation",
25+
"desc": "Perfect for null checks, range validation, and defensive copies."
26+
},
27+
{
28+
"icon": "📖",
29+
"title": "Clearer intent",
30+
"desc": "Compact syntax emphasizes validation, not boilerplate."
31+
}
32+
],
33+
"support": {
34+
"state": "available",
35+
"description": "Widely available since JDK 16 (March 2021)"
36+
},
37+
"prev": "language/static-members-in-inner-classes",
38+
"next": null,
39+
"related": [
40+
"language/records-for-data-classes",
41+
"language/flexible-constructor-bodies",
42+
"errors/record-based-errors"
43+
]
44+
}

content/language/default-interface-methods.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"description": "Available since JDK 8 (March 2014)."
3636
},
3737
"prev": "tooling/aot-class-preloading",
38-
"next": null,
38+
"next": "language/markdown-javadoc-comments",
3939
"related": [
4040
"language/private-interface-methods",
4141
"language/pattern-matching-instanceof",
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"id": 92,
3+
"slug": "markdown-javadoc-comments",
4+
"title": "Markdown in Javadoc comments",
5+
"category": "language",
6+
"difficulty": "beginner",
7+
"jdkVersion": "23",
8+
"oldLabel": "Java 8",
9+
"modernLabel": "Java 23+",
10+
"oldApproach": "HTML-based Javadoc",
11+
"modernApproach": "Markdown Javadoc",
12+
"oldCode": "/**\n * Returns the {@code User} with\n * the given ID.\n *\n * <p>Example:\n * <pre>{@code\n * var user = findUser(123);\n * }</pre>\n *\n * @param id the user ID\n * @return the user\n */\npublic User findUser(int id) { ... }",
13+
"modernCode": "/// Returns the `User` with\n/// the given ID.\n///\n/// Example:\n/// ```java\n/// var user = findUser(123);\n/// ```\n///\n/// @param id the user ID\n/// @return the user\npublic User findUser(int id) { ... }",
14+
"summary": "Write Javadoc comments in Markdown instead of HTML for better readability.",
15+
"explanation": "Java 23 introduces /// Markdown-style Javadoc comments as an alternative to the traditional /** */ HTML-based format. Markdown syntax is more natural to write and read, with support for code blocks, emphasis, lists, and links. The compiler converts Markdown to HTML for javadoc output.",
16+
"whyModernWins": [
17+
{
18+
"icon": "📖",
19+
"title": "Natural syntax",
20+
"desc": "Use backticks for inline code and ``` for blocks instead of HTML tags."
21+
},
22+
{
23+
"icon": "✍️",
24+
"title": "Easier to write",
25+
"desc": "No need for {@code}, <pre>, <p> tags — just write Markdown."
26+
},
27+
{
28+
"icon": "👁",
29+
"title": "Better in editors",
30+
"desc": "Markdown renders beautifully in modern IDEs and text editors."
31+
}
32+
],
33+
"support": {
34+
"state": "available",
35+
"description": "Available since JDK 23 (Sept 2024)"
36+
},
37+
"prev": "language/default-interface-methods",
38+
"next": "language/static-methods-in-interfaces",
39+
"related": [
40+
"language/text-blocks-for-multiline-strings",
41+
"language/records-for-data-classes",
42+
"language/type-inference-with-var"
43+
]
44+
}

0 commit comments

Comments
 (0)