It is possible to have your cake and eat it too.
The Streams API in Java 8 doesn't handle exceptions or resources properly. Superior Streams are a wrapper around the JDK Streams API that adds proper exception passing and resource management without complicating the API.
New: Experimental Collections API replacement featuring regular and immutable versions of Map, Set and List. This is integrated to a new version of the Stream API.
Lambda expressions throwing IOExceptions are just as simple to use as those throwing unchecked exceptions:
//*/
static Object[] example1(IOStream<File> s3, Stream<File> s33) {
IOFunction<File, JarFile> toJarFile1 = JarFile::new;
IOStream<JarFile> s4 = s3.map(toJarFile1);
// Using JDK Streams requires twisting and turning:
Function<File, JarFile> toJarFile2 = (File file) -> {
try {
return new JarFile(file);
} catch(IOException e) {
throw new UncheckedIOException(e);
}
};
Stream<JarFile> s43 = s33.map(toJarFile2);
return new Object[] {s4,s43}; }/*/
Resources are released as soon as they are no longer needed, automatically and transparently:
//*/
static void example2(Path install, Predicate<Path> isJdk) throws IOException {
IOStream<Path> s1 = Files.list(install);
IOStream<Path> s2 = s1.filter(isJdk);
for(Path path : s1.iterable()) {
System.out.println(path);
}
for(Path path : s2.iterable()) {
System.out.println(path);
}
// JDK Streams need to be manually tracked at each use site:
try(java.util.stream.Stream<Path> s11 = java.nio.file.Files.list(install);
java.util.stream.Stream<Path> s12 = java.nio.file.Files.list(install);) {
java.util.stream.Stream<Path> s22 = s12.filter(isJdk);
for(Path path : (Iterable<Path>) () -> s11.iterator()) {
System.out.println(path);
}
for(Path path : (Iterable<Path>) () -> s22.iterator()) {
System.out.println(path);
}
}
}/*/
Superior Streams can be freely reused as many times as needed:
//*/
static Object[] example3(List<String> JDK_PROJECTS1, java.util.List<String> JDK_PROJECTS2) {
Stream<String> projects1 = JDK_PROJECTS1.stream();
Predicate<String> isPrefix1 = (String path) -> projects1.anyMatch(path::startsWith);
// Each Stream from JDK can only be used once or the result is an exception at runtime:
Supplier<java.util.stream.Stream<String>> projects2 = () -> JDK_PROJECTS2.stream();
Predicate<String> isPrefix2 = (String path) -> projects2.get().anyMatch(path::startsWith);
return new Object[] {isPrefix1,isPrefix2}; }/*/
Mutable and immutable versions:
//*/
static Object[] example4() {
ArrayList<String> list = new ArrayList<>();
HashSet<String> set = list.add("1").add("2").toHashSet();
// Immutable versions use the same API but return copies when changed:
List<String> immutableList = list.toList();
Set<String> immutableSet = set.toSet().replaceAll(s -> "log: " + s);
return new Object[] {immutableList,immutableSet}; }/*/
With exceptions passing through as expected:
//*/
static FileTime getLastModifiedTime(Path path) throws IOException {
return lastModifiedCache.computeIfAbsent(path, p -> Files.getLastModifiedTime(path)).get(path);
}
private static HashMap<Path, FileTime> lastModifiedCache = new HashMap<>();
// Standard library version requires lots of catching and re-throwing:
static FileTime getLastModifiedTime2(Path path) throws IOException {
try {
return lastModifiedCache2.computeIfAbsent(path, p -> {
try {
return Files.getLastModifiedTime(path);
} catch(IOException e) {
throw new UncheckedIOException(e);
}
});
} catch(UncheckedIOException e) {
throw e.getCause();
}
}
private static java.util.Map<Path, FileTime> lastModifiedCache2 = new java.util.HashMap<>();
/*/
Image manipulation using red, green, blue channels:
//*/
static void example6() throws IOException {
RGBStream stream = Streams.loadImageInRGB("pagoda.jpg");
stream.swapRedAndGreen().save("pagoda_rg.jpg");
stream.swapRedAndBlue().save("pagoda_rb.jpg");
stream.swapAlphaAndBlue().save("pagoda_ab.png");
stream.setRed(255).save("pagoda_bright_red.png");
}/*/
Image color manipulation in HSB changing hue, saturation and brightness values:
//*/
static void example7() throws IOException {
HSBStream hsb = Streams.loadImageInHSB("pagoda.jpg");
hsb.mapBrightness((h, s, b, a) -> b * 0.25).save("pagoda_dark.jpg");
hsb.mapHue((h, s, b, a) -> h + 60).save("pagoda_altered_hue.jpg");
}/*/
Gamma adjustments:
//*/
static void example8() throws IOException {
RGBStream stream = Streams.loadImageInRGB("pagoda.jpg");
stream.gammaExpand(2.4).save("pagoda_texture.jpg");
HSBStream bw = stream.toBlackAndWhite();
bw.save("pagoda_bw.jpg");
bw.gammaCompress(0.5).save("pagoda_bw2.jpg");
}/*/
//*/
static ArrayList<String> removeBadWords(List<String> list) {
return Streams.where(list, s -> s.contains("fuck") == false);
}/*/
Or rather, they are being gradually tested over time.
Your choice of:
Several collections classes in the utils.lists2 package are based on classes from gs-collections by Goldman Sachs and are licensed under the Apache License, Version 2.0.
The image pagoda.jpg, by the author plusgood, is licensed under the Creative Commons Attribution 2.0 Generic license. Downloaded from the Wikimedia Commons.