• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

lambda expressions and streams

 
Greenhorn
Posts: 12
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
 
Rancher
Posts: 4801
50
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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.
 
Sheriff
Posts: 7125
184
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh, and you collect a new map showing you the result you want.
 
Marshal
Posts: 79177
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • 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
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks very much for a great explanation. :-)
     
    Campbell Ritchie
    Marshal
    Posts: 79177
    377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    tim ledger wrote:Thanks very much . . .

    That's a pleasure
     
    He's my best friend. Not yours. Mine. You can have this tiny ad:
    a bit of art, as a gift, that will fit in a stocking
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic