As an exercise, I decide to rewrite some code of mine to use lambda expression. The code should check if a given string is a path to a file with .pdf extension and then it should display all the files that meet this requirement. This so what I've already come up with:
Files.newDirectoryStream(Paths.get(args[0]), path -> path.toFile()
.toString()
.endsWith(".pdf"))
.forEach(System.out::println);
This code fails at one point: it also displays directories. Could you tell me why the following code fails to compile?
Files.newDirectoryStream(Paths.get(args[0]), path -> path.toFile()
.isFile()
.toString()
.endsWith(".pdf"))
.forEach(System.out::println);
Your second code fails to compile because isFile returns a boolean. Once you have a boolean, file name is gone; even if you could convert it to String, matching its suffix to ".pdf" would fail anyway.
You are testing two separate conditions, so you should test them in two separate checks:
Files.newDirectoryStream(Paths.get(args[0]), path ->
Files.isRegularFile(path) && path.toString().endsWith(".pdf")
).forEach(System.out::println);
Note that path.toString().endsWith(...) can be checked without converting Path to File.
Because the compiler expects to have a boolean as second argument of
newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
Filter being a functional interface defined as :
boolean accept(T entry) throws IOException;
But here :
.isFile()
.toString()
a String is returned.
Make things in two times by combining two boolean expressions :
Files.newDirectoryStream(Paths.get(args[0]), path ->
Files.isRegularFile(path)
&& path.toString().endsWith(".pdf"))
.forEach(System.out::println);
In addition to Andreas comment about :
path.toFile().toString().endsWith(".pdf"))
that may be abbreviated by : path.toString().endsWith(".pdf"), you could also replace
path.toFile().isFile() by Files.isRegularFile(path).
It allows to rely only on the java.nio.file API rather that mixing it with the java.io.file API.
Related
I am new to apache spark and trying to run the wordcount example . But intellij editor gives me the error at line 47 Cannot resolve method 'flatMap()' error.
Edit :
This is the line where I am getting the error
JavaRDD<String> words = lines.flatMap(s -> Arrays.asList(SPACE.split(s)).iterator());
It looks like you're using an older version of Spark that expects Iterable rather than Iterator from the flatMap() function. Try this:
JavaRDD<String> words = lines.flatMap(s -> Arrays.asList(SPACE.split(s)));
See also Spark 2.0.0 Arrays.asList not working - incompatible types
Stream#flatMap is used for combining multiple streams into one, so the supplier method you provided must return a Stream result.
you can try like this:
lines.stream().flatMap(line -> Stream.of(SPACE.split(line)))
.map(word -> // map to JavaRDD)
flatMap method take a FlatMapFunctionas parameter which is not annotated with #FunctionalInterface. So indeed you can not use it as a lambda.
Just build a real FlatMapFunctionobject as parameter and you will be sure of it.
flatMap() is Java 8 Stream API. I think you should check the IDEA compile java version.
compile java version
I have tried to get all the solution files(*.sln) in a given path and print it individually by split the string(each solution file path) using comma delimiter. Programming script language am using is Jenkins Groovy. Am getting the below specified error when build the Jenkins job. Any one please look into this and guide me to proceed in a right way.
def finder = new FileNameFinder()
def files = finder.getFileNames 'D:\jobs', '**/*.sln'
def resultList = files.tokenize(",")
for(i=0; i<resultList.size();i++)
{
println resultList[i]
}
Error Details:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.tokenize() is applicable for argument types: (java.lang.String) values: [,]
Possible solutions: toUnique(), toUnique(), toUnique(java.util.Comparator), takeWhile(groovy.lang.Closure), toUnique(groovy.lang.Closure), toUnique(java.util.Comparator)
Thanks in advance!!
Myself itself found an answer for my above problem. Please find below the modified working code.
def finder = new FileNameFinder()
def files = finder.getFileNames 'D:\jobs', '**/*.sln'
assert files instanceof List
println files.size()+" solution files found in the given path. Below are the found solution files details. \n"
for(i=0;i<files.size();i++)
{
println files[i];
}
Thanks
Im trying to add arguments to the arguments list of a MethodInvocation and it doesnt seem to work, I can remove objects but I cant see to add them.
My end goal is to take 2 MethodInvocation that invoke the same method with different arguments and convert it to 1 MethodInvocation that has a ConditionalExpression as an argument.
Example:
if (A){
System.out.println("hi");
} else {
System.out.println("hey");
}
Will be converted to:
System.out.println((A ? "hi" : "hey"));
So I would also appreciate it if someone knwos how to convert the argument list to 1 big Expression I can place in the ConditionalExpression.
Thanks!
EDIT: sorry forgot to mention is it a code formatting plug-in for ecplise
EDIT2: the code I am trying to run:
final ExpressionStatement thenStmnt=(ExpressionStatement)((Block)node.getThenStatement()).statements().get(0),
elseStmnt=(ExpressionStatement)((Block)node.getElseStatement()).statements().get(0);
MethodInvocation thenMethod=(MethodInvocation)thenStmnt.getExpression(),
elseMethod=(MethodInvocation)elseStmnt.getExpression();
final MethodInvocation method=ast.newMethodInvocation();
method.setName(ast.newSimpleName("add"));
method.arguments().add(0, elseMethod.arguments().get(0));
ast is a given leagal AST and node is a given leagal IfStatement.
Solved, problem was here:
method.arguments().add(0, elseMethod.arguments().get(0));
If you want to take or copy something that is already part of your original code, meaning already exist in the AST you have to use r.createCopyTarget, like so:
method.arguments().add(0, r.createCopyTarget(elseMethod.arguments().get(0)));
Is there a concise, idiomatic way (maybe using Apache Commons) to specify common combinations of OpenOption like StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
These are the easy possibilities you have.
Static Imports, to increase readability:
import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static java.nio.file.StandardOpenOption.WRITE;
OpenOption[] options = new OpenOption[] { WRITE, CREATE_NEW };
Use defaults:
//no Options anyway
Files.newBufferedReader(path, cs)
//default: CREATE, TRUNCATE_EXISTING, and WRITE not allowed: READ
Files.newBufferedWriter(path, cs, options)
//default: READ not allowed: WRITE
Files.newInputStream(path, options)
//default: CREATE, TRUNCATE_EXISTING, and WRITE not allowed: READ
Files.newOutputStream(path, options)
//default: READ do whatever you want
Files.newByteChannel(path, options)
Finally it's possible to specify optionsets like this:
Files.newByteChannel(path, EnumSet.of(CREATE_NEW, WRITE));
The best suggestion I can offer would be to cheat on the equivalence of T... and T[], which one of the other stackoverflow discussions says should work
Can I pass an array as arguments to a method with variable arguments in Java?
So...
OpenOption myOptions[] = {StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING};
OutputStream foo=OutputStream.newOutputStream(myPath,myOptions);
Caveat: Untested.
java.nio.file.Files has 5 flavours of methods with OpenOption varargs parameters:
Files
.newBufferedWriter(...)
.write(...)
.newOutputStream(...)
.newInputStream(...)
.newByteChannel(...)
They directly don't restrict any OpenOption combination, but all of them under the hood call to some of these 3 methods at java.nio.file.spi.FileSystemProvider:
FileSystemProvider
.newInputStream(Path, OpenOption...)
.newOutputStream(Path, OpenOption...)
.newByteChannel(Path, Set<? extends OpenOption>, FileAttribute<?>...)
FileSystemProvider.newInputStream(...) is called by: Files.newInputStream(...)
FileSystemProvider.newOutputStream(...) is called by:
Files
.newBufferedWriter(...)
.newOutputStream(...)
.write(...)
abstract FileSystemProvider.newByteChannel(...) is called by:
Files.newByteChannel(...)
FileSystemProvider.newInputStream(...)
FileSystemProvider.newOutputStream(...)
OptenOption combination restrictions:
FileSystemProvider.newInputStream(...)
UnsupportedOperationException: WRITE || APPEND
FileSystemProvider.newOutputStream(...)
Implicitly: WRITE
IllegalArgumentException: READ
default (if non options): CREATE && TRUNCATE_EXISTING
The abstract FileSystemProvider.newByteChannel(...) method has a platform dependent implementation, which may extend the OpenOption combination restrictions (as in sun.nio.fs.WindowsFileSystemProvider).
All Files method which uses OpenOption vargars under the hood ends in the abstract FileSystemProvider.newByteChannel(...), which implementation is platform dependent. So, the OpenOption combinations restriction in Files methods are platform dependent.
I switched an existing code base to Java 7 and I keep getting this warning:
warning: File for type '[Insert class here]' created in the last round
will not be subject to annotation processing.
A quick search reveals that no one has hit this warning.
It's not documented in the javac compiler source either:
From OpenJDK\langtools\src\share\classes\com\sun\tools\javac\processing\JavacFiler.java
private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException {
checkNameAndExistence(name, isSourceFile);
Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
JavaFileObject.Kind kind = (isSourceFile ?
JavaFileObject.Kind.SOURCE :
JavaFileObject.Kind.CLASS);
JavaFileObject fileObject =
fileManager.getJavaFileForOutput(loc, name, kind, null);
checkFileReopening(fileObject, true);
if (lastRound) // <-------------------------------TRIGGERS WARNING
log.warning("proc.file.create.last.round", name);
if (isSourceFile)
aggregateGeneratedSourceNames.add(name);
else
aggregateGeneratedClassNames.add(name);
openTypeNames.add(name);
return new FilerOutputJavaFileObject(name, fileObject);
}
What does this mean and what steps can I take to clear this warning?
Thanks.
The warning
warning: File for type '[Insert class here]' created in the last round
will not be subject to annotation processing
means that your were running an annotation processor creating a new class or source file using a javax.annotation.processing.Filer implementation (provided through the javax.annotation.processing.ProcessingEnvironment) although the processing tool already decided its "in the last round".
This may be problem (and thus the warning) because the generated file itself may contain annotations being ignored by the annotation processor (because it is not going to do a further round).
The above ought to answer the first part of your question
What does this mean and what steps can I take to clear this warning?
(you figured this out already by yourself, didn't you :-))
What possible steps to take? Check your annotation processors:
1) Do you really have to use filer.createClassFile / filer.createSourceFile on the very last round of the annotaion processor? Usually one uses the filer object inside of a code block like
for (TypeElement annotation : annotations) {
...
}
(in method process). This ensures that the annotation processor will not be in its last round (the last round always being the one having an empty set of annotations).
2) If you really can't avoid writing your generated files in the last round and these files are source files, trick the annotation processor and use the method "createResource" of the filer object (take "SOURCE_OUTPUT" as location).
In OpenJDK test case this warning produced because processor uses "processingOver()" to write new file exactly at last round.
public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
if (renv.processingOver()) { // Write only at last round
Filer filer = processingEnv.getFiler();
Messager messager = processingEnv.getMessager();
try {
JavaFileObject fo = filer.createSourceFile("Gen");
Writer out = fo.openWriter();
out.write("class Gen { }");
out.close();
messager.printMessage(Diagnostic.Kind.NOTE, "File 'Gen' created");
} catch (IOException e) {
messager.printMessage(Diagnostic.Kind.ERROR, e.toString());
}
}
return false;
}
I modified original example code a bit. Added diagnostic note "File 'Gen' created", replaced "*" mask with "org.junit.runner.RunWith" and set return value to "true". Produced compiler log was:
Round 1:
input files: {ProcFileCreateLastRound}
annotations: [org.junit.runner.RunWith]
last round: false
Processor AnnoProc matches [org.junit.runner.RunWith] and returns true.
Round 2:
input files: {}
annotations: []
last round: true
Note: File 'Gen' created
Compilation completed successfully with 1 warning
0 errors
1 warning
Warning: File for type 'Gen' created in the last round will not be subject to annotation processing.
If we remove my custom note from log, it's hard to tell that file 'Gen' was actually created on 'Round 2' - last round. So, basic advice applies: if in doubt - add more logs.
Where is also a little bit of useful info on this page:
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html
Read section about "ANNOTATION PROCESSING" and try to get more info with compiler options:
-XprintProcessorInfo
Print information about which annotations a processor is asked to process.
-XprintRounds Print information about initial and subsequent annotation processing rounds.
I poked around the java 7 compiler options and I found this:
-implicit:{class,none}
Controls the generation of class files for implicitly loaded source files. To automatically generate class files, use -implicit:class. To suppress class file generation, use -implicit:none. If this option is not specified, the default is to automatically generate class files. In this case, the compiler will issue a warning if any such class files are generated when also doing annotation processing. The warning will not be issued if this option is set explicitly. See Searching For Types.
Source
Can you try and implicitly declare the class file.