2

I am new in functional programming in java 1.8. I have simple loop like the below code:

File folder = new File("./src/renamer/Newaudio");
File[] listOfFiles = folder.listFiles();

for (int i = 0; i < listOfFiles.length; i++) {
    System.out.println("Here is file number: " + i);
}

I am going to change the upper for loop to the functional format using the arrow function (like a lambda).

listOfFiles.map((file) = > {
        System.out.println("Here is file number: " + i);
});

Unfortunately, it complains with:

Cannot invoke map((<no type> file) -> {}) on the array type File[]

Why i get this error? how i can resolve it?

I like to learn about Lambda, so i am not interested to the foreach

3
  • 7
    Use .forEach instead of .map. Note that you can use Files.list(Paths.get("./src/renamer/Newaudio")).forEach(...) to jump into the Stream API directly.
    – aioobe
    Commented Jan 16, 2017 at 14:03
  • 2
    What's i in your lambda? Commented Jan 16, 2017 at 14:04
  • 6
    If you're using Java 8, Don't use the File class. It's outdated and should be laid to rest. Use Path and Files. Commented Jan 16, 2017 at 14:04

3 Answers 3

4

You can use IntStream.range to print the file numbers only

    IntStream.range(0,listOfFiles.length).forEach(System.out::println);

or To print Content of array you can use

    Arrays.stream(listOfFiles).forEach(System.out::println);

Compiler will convert your method reference to lambda expression at compile time so this

    Arrays.stream(listOfFiles).forEach(System.out::println);

will be converted into this

=>  Arrays.stream(listOfFiles).forEach(i->System.out.println(i));

With lambda you can use the expended lambda {} as well

=> Arrays.stream(listOfFiles).forEach(i->{
       if (!i.isHidden()) { // don't print hidden files
           System.out.println(i);               
       }
   });

So listFiles returns null is file is not a directory and for simplicity you can simply put a check at the first place

    File folder = new File("./src/renamer/Newaudio");
    if (folder.isDirectory()) {
        File[] listOfFiles = folder.listFiles();
        Arrays.stream(listOfFiles).forEach(i->System.out.println(i));           
    }

Reference

Lambda and Method reference concise details

2
  • I like to learn about Lambda, so i am not interested to the foreach
    – Sal-laS
    Commented Jan 16, 2017 at 14:07
  • 5
    @Salman you seem to misunderstand what "Lambda" is. The lambda is the parameter of the map or forEach method, not the map method itself. Commented Jan 16, 2017 at 14:07
3

folder.listFiles() should be wrapped with the Optional.ofNullable to prevent from a NullPointerException. It can return null if the given pathname does not denote a directory, or if an I/O error occurs.

Stream.of(ofNullable(folder.listFiles()).
          orElseThrow(() -> new IllegalArgumentException("It's not a directory!")))
      .forEach(f -> {});

where the forEach method could take these arguments:

(1) an anonymous class

new Consumer<File>() {
    public @Override void accept(File file) {
        System.out.println(file);
    }
}

(2) expended lambda expressions

(File f) -> { System.out.println(f); }
(f) -> { System.out.println(f); }

(3) simplified lambda expressions

f -> { System.out.println(f); }
f -> System.out.println(f)

(4) a method reference

System.out::println
3
  • when i used the multiple line format of lambda (f->{system.out.pringlin()}) it complains that Syntax error, insert "AssignmentOperator Expression" to complete Expression - The left-hand side of an assignment must be a variable
    – Sal-laS
    Commented Jan 16, 2017 at 14:25
  • 1
    @Salman: The System class starts with an upper case S, the method is println, not pringlin, and there has to be a semi-colon after the statement.
    – Holger
    Commented Jan 16, 2017 at 15:12
  • 1
    @Andrew Tobilko: forEach (not foerEach) can take more than these four kind of arguments. A named class implementing Consumer works as well, as any other expression leading to an instance of that type, like reading a variable containing an existing instance or invoking a factory method. And you can pass null, the compiler won’t object, though the result is predictably of little use…
    – Holger
    Commented Jan 16, 2017 at 15:17
3
IntStream.range(0, listOfFiles.length).forEach(file -> {
    System.out.println(file);
});
1
  • 3
    Note: OP's original code did not print the file names but just the numbers.
    – tobias_k
    Commented Jan 16, 2017 at 14:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.