I want to find all files in files tree. In Java I'd write something like:
try(Stream<Path< paths = Files.find(startingPath, maxDepth,
(path, attributes) -> !attributes.isDirectory())) {
paths.forEach(System.out::println);
}
But I am using kotlin, and came up with this:
Files.find(startingPath,maxDepth,
{ (path, basicFileAttributes) -> !basicFileAttributes.isDirectory()}
).use { println(it) }
However, this gives me error:
Cannot infer a type for this parameter. Please specify it explicitly.
Type mismatch:
Required: BiPredicate< Path!, BasicFileAttributes! >!
Found: (???) -> Boolean
Any idea how to use BiPredicate in this case?
Thanks in advance
BiPredicate
is a Java class, Kotlin function types are not directly compatible. This is due to missing SAM conversions, also explained in my recent answer here.
What you need to pass is an object matcher
of type BiPredicate<Path, BasicFileAttributes>
. To clarify, something like this:
val matcher = object : BiPredicate<Path, BasicFileAttributes>
{
override fun test(path: Path, basicFileAttributes: BasicFileAttributes): Boolean
{
return !basicFileAttributes.isDirectory()
}
}
This can be simplified to:
val matcher = BiPredicate<Path, BasicFileAttributes> { path, basicFileAttributes ->
!basicFileAttributes.isDirectory()
}
When you pass it to Files.find()
, Kotlin is even able to infer the generic parameter types. So in total, your expression would be:
Files.find(startingPath, maxDepth, BiPredicate { path, basicFileAttributes ->
!basicFileAttributes.isDirectory()
}).use { println(it) }
You had two problems there. Use BiPredicate { x, y -> code }
for the type mismatch error the compiler gives you, and then get the actually do what it intends to do by replacing .use
with forEach
. Otherwise it prints the stream object.
Files.find(startingPath, maxDepth,
BiPredicate { path, basicFileAttributes -> !basicFileAttributes.isDirectory() }
).forEach { println(it) }