Skip to content

Commit

Permalink
Add ProcessDictionaryV2 class and update Gradle Github workflow
Browse files Browse the repository at this point in the history
A new ProcessDictionaryV2 class is added in this commit which implements various methods for processing text files. Additionally, the workflow file for Github actions has been created for Gradle based projects, specifying jobs to build the code and run tests across multiple operating systems. A minor update was also introduced in the build.gradle.kts by tweaking the JVM arguments.
  • Loading branch information
kousen committed Jul 4, 2024
1 parent b8069cb commit 288674f
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 3 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Java CI with Gradle

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Grant execute permission for gradlew
if: runner.os != 'Windows'
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test

- name: Upload build reports
uses: actions/upload-artifact@v3
with:
name: build-reports-${{ matrix.os }}
path: build/reports/

- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: test-results-${{ matrix.os }}
path: build/test-results/
5 changes: 2 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ dependencies {
testImplementation(libs.bundles.mockito)
testImplementation(libs.wiremock)
testImplementation("com.jayway.jsonpath:json-path:2.9.0")

}

tasks.withType<JavaCompile>().configureEach {
Expand All @@ -48,10 +47,10 @@ tasks.withType<JavaCompile>().configureEach {

tasks.withType<Test>().configureEach {
useJUnitPlatform()
jvmArgs("--enable-preview")
jvmArgs("--enable-preview", "-XX:+EnableDynamicAgentLoading", "-Xshare:off")
setMaxParallelForks(Runtime.getRuntime().availableProcessors() / 2 + 1)
}

tasks.withType<JavaExec>().configureEach {
jvmArgs("--enable-preview")
jvmArgs("--enable-preview", "-XX:+EnableDynamicAgentLoading", "-Xshare:off")
}
141 changes: 141 additions & 0 deletions src/main/java/com/kousenit/fileio/ProcessDictionaryV2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.kousenit.fileio;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ProcessDictionaryV2 {
private static final Path DICTIONARY = Path.of("src/main/resources/dict/words");

private <T> T processFile(Function<Stream<String>, T> processor) {
try (Stream<String> words = Files.lines(DICTIONARY)) {
return processor.apply(words);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private int maxLength() {
return processFile(words ->
words.mapToInt(String::length)
.max()
.orElse(0));
}

public void printNTenLongestWords(int n) {
System.out.println("\nTen Longest Words:");
int maxForFilter = maxLength() - 10;
processFile(words -> {
words.filter(s -> s.length() > maxForFilter)
.sorted(Comparator.comparingInt(String::length).reversed())
.limit(n)
.forEach(w -> System.out.printf("%s (%d)%n", w, w.length()));
return null;
});
}

public void printWordsOfEachLength() {
System.out.println("\nList of words of each length:");
int maxForFilter = maxLength() - 5;
processFile(words -> {
words.filter(s -> s.length() > maxForFilter)
.collect(Collectors.groupingBy(String::length))
.forEach((len, wordList) -> System.out.printf("%d: %s%n", len, wordList));
return null;
});
}

public void printHowManyWordsOfEachLength() {
System.out.println("\nNumber of words of each length:");
int maxForFilter = maxLength() - 10;
printWordLengthStats(s -> s.length() > maxForFilter);
}

public void teeingCollectorDoesBoth() {
System.out.println("\nTeeing collector:");
int maxForFilter = maxLength() - 10;
processFile(words -> {
var map = words.filter(s -> s.length() > maxForFilter)
.collect(Collectors.teeing(
Collectors.groupingBy(String::length, Collectors.counting()),
Collectors.groupingBy(String::length),
(map1, map2) -> map1.entrySet()
.stream()
.collect(
Collectors.toMap(
Map.Entry::getKey,
e -> Map.of("count", e.getValue(),
"words", map2.get(e.getKey()))
)
)
));
map.forEach((k, v) -> System.out.printf("%d: %s%n", k, v));
return null;
});
}

public void teeingCollectorExample() {
System.out.println("\nTeeing collector example:");
processFile(words -> {
record WordStats(long totalWords, double averageLength, String longestWord) {
}

int maxForFilter = maxLength() - 10;
WordStats wordStats = words.filter(w -> w.length() >= maxForFilter)
.collect(Collectors.teeing(
Collectors.counting(),
Collectors.teeing(
Collectors.averagingDouble(String::length),
Collectors.maxBy(Comparator.comparingInt(String::length)),
(avg, maxWord) -> new WordStats(0, avg, maxWord.orElse(""))
),
(count, stats) -> new WordStats(count, stats.averageLength(), stats.longestWord())
));

System.out.printf("Words with length >= %d:%n", maxForFilter);
System.out.printf("Total words: %d%n", wordStats.totalWords());
System.out.printf("Average length: %.2f%n", wordStats.averageLength());
System.out.printf("Longest word: %s (length: %d)%n",
wordStats.longestWord(), wordStats.longestWord()
.length());

return null;
});
}

public void printSortedMapOfWords() {
System.out.println("\nNumber of words of each length (desc order):");
int maxForFilter = maxLength() - 10;
printWordLengthStats(s -> s.length() > maxForFilter);
}

private void printWordLengthStats(Function<String, Boolean> filter) {
processFile(words -> {
Map<Integer, Long> map = words.filter(filter::apply)
.collect(Collectors.groupingBy(String::length, Collectors.counting()));

map.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
.forEach(e -> System.out.printf("Length %d: %d words%n", e.getKey(), e.getValue()));
return null;
});
}

@SuppressWarnings("unused")
public static void main(String[] args) {
var processDictionary = new ProcessDictionaryV2();
processDictionary.printNTenLongestWords(10);
processDictionary.printWordsOfEachLength();
processDictionary.printHowManyWordsOfEachLength();
processDictionary.teeingCollectorDoesBoth();
processDictionary.teeingCollectorExample();
processDictionary.printSortedMapOfWords();
}
}

0 comments on commit 288674f

Please sign in to comment.