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. 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

Sign up to request clarification or add additional context in comments.

2 Comments

I like to learn about Lambda, so i am not interested to the foreach
@Salman you seem to misunderstand what "Lambda" is. The lambda is the parameter of the map or forEach method, not the map method itself.
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 Comments

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
@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.
@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…
3
IntStream.range(0, listOfFiles.length).forEach(file -> {
    System.out.println(file);
});

1 Comment

Note: OP's original code did not print the file names but just the numbers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.