Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Knute Snortum
  • Paul Clapham
  • Tim Cooke
Sheriffs:
  • Liutauras Vilda
  • Jeanne Boyarsky
  • Bear Bibeault
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Ron McLeod
  • Piet Souris
  • Frits Walraven
Bartenders:
  • Ganesh Patekar
  • Tim Holloway
  • salvin francis

lambda expressions and streams  RSS feed

 
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

How do I write a lambda expression, with two variables, as a filter in a stream?

Here is what I am trying to do:

       NavigableMap<Integer, String> mymap = new TreeMap<>();
       mymap.put(90, "Sophia");
       mymap.put(20, "Isabella");
       mymap.put(10, "Emma");
       mymap.put(50, "Olivea");
       mymap.entrySet().stream().filter((Integer i, String s) -> i > 40).

The error that I am getting says: "Incompatible types. Incompatible types in lambda expression"

Thanks

Tim
 
Master Rancher
Posts: 4076
47
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The entrySet() method returns a Set<Map.Entry<K,V>> so the parameter to the lambda is a Map.Entry<Integer, String> in your case.
 
Marshal
Posts: 5988
155
Chrome Eclipse IDE Java Postgres Database Ubuntu VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And if you don't need the String value, you can simplify the code to:
 
tim ledger
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Figured it out:

You can get the values andd the keys as in the filter below.

       Map<Integer, String> passed = mymap.entrySet().stream().filter(p -> p.getKey() > 40)
               .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
       System.out.println("Mark \tName");
       passed.forEach((i, s) -> System.out.printf("%d \t%s\n", i, s));
 
tim ledger
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, and you collect a new map showing you the result you want.
 
Marshal
Posts: 64494
225
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Duplicating this discussion in our Java8 forum.

Go through the methods of the Stream interface, and you will find they are described as terminal operations or intermediate operations (gross oversimplification warning ‍). Those labelled intermediate return a Stream, and those called terminal don't return a Stream; they might be void or return something different. Every time you call a method which is an intermediate operation, it creates a reference to a new Stream. That may seem expensive in memory, but it isn't. The Streams are probably created on the stack because you usually create them as local variables and they go out of scope as soon as the statement finishes. There is no point in having a Stream with more scope, becaus you cannot wind it back to its beginning and start again. You need a new Stream. Each Stream reference created will point to an object which executes one part of the action you want. If you execute yoru code on an IDE like Eclipse, hover your mouse over each of the method calls and you will get a popup with the type of Stream, i.e. the type actually returned from each method call. That shou‍ld allow you to see how the different Streams handle the data they are processing.

tim ledger wrote:

Let's reformat that code, with a slightly different indentation convention so all the dots align vertically:-Now, if you have a Map<XYZ, Integer>, and you hover your mouse on the different lines the popups will say something like this:-
  • Line 1: Set<Map.Entry<XYZ, Integer>>
  • Line 2: Stream<Map.Entry<XYZ, Integer>>
  • Line 3: Stream<Map.Entry<XYZ, Integer>> Note the filer method is likely to return a Stream of exactly the same type.
  • Line 4: Map<XYZ, Integer>>
  • You will probably find that sort of information makes it easier to follow what is happening throughout the whole procedure. If you add a peek call anywhere, you will find that nothing happens until the collect method (which is a terminal operation) starts, because Streams use lazy execution.

    If you go back to the Stream documentation, you will find the phrases like intermediate operation are hyperlinks and you will get more information if you click them.

    [edit]I seem to have got the K and V types the wrong way round in what I wrote earlier. I shall leave it to the reader to work out how to correct my error. Sorry.
     
    tim ledger
    Greenhorn
    Posts: 12
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks very much for a great explanation. :-)
     
    Campbell Ritchie
    Marshal
    Posts: 64494
    225
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    tim ledger wrote:Thanks very much . . .

    That's a pleasure
     
    Curse your sudden but inevitable betrayal! And this tiny ad too!
    how do I do my own kindle-like thing - without amazon
    https://coderanch.com/t/711421/engineering/kindle-amazon
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!