2

I am just started to get familiar with lambdas. I can solve my problem with an easier way.. but i think this version of my solution would be more impressive. Let me explain...

I have a List<Object> .. i would like to iterate through all the objects inside the list, and i would like to call a method depend on one of the Object's field. The method returns a boolean. And this is the main part of my problem. I would like to collect them into a Map<Boolean, Object> so if the method runned successfully i need a K:true,V:Object in my beautiful Map if not runned successfully i want a K:false,V:Object in the Map... and so on.


Here is my code: (Where 'data' is my List<Object>)

Map<Boolean, ToDo> result = data.stream().collect(Collectors.toMap(
            task -> {
                if (task.getTask().equalsIgnoreCase("Foo")) {
                    foo.handle(task);
                } else if (task.getTask().equalsIgnoreCase("Boo")) {
                    boo.handle(task);
                }
            }, task -> task
    ));
Marwan Ansari
  • 123
  • 1
  • 10
csirkeautomata
  • 177
  • 3
  • 16
  • How are you going to handle key conflicts here? What if two objects have the same foo value and produces the same key? – Ravindra Ranwala Jan 26 '19 at 03:25
  • That's fine. I mean there will be objects with same foo value. Every objects came from db so they have different ids.. the Map keys just needs for me to decide to delete them or not later on from the db. :) – csirkeautomata Jan 26 '19 at 09:05

2 Answers2

2

First populate a map with the key-value mappings where keys are from the if check and values are handler implementations such as foo, bar etc. Then use that map in your lambda expressions like so,

Map<String, Handler> nameToHandler = new HashMap<>();
nameToHandler.put("Foo", new FooHandler());
nameToHandler.put("Bar", new BarHandler());

Map<Boolean, List<ToDo>> result = data.stream()
    .collect(Collectors.partitioningBy(task -> 
        nameToHandler.get(task.getTask()).handleTask(task)));

Notice that the objects with the same key are collected into a container using a downstream collector.

Assumptions: FooHandler and BarHandler implements the Handler interface. Ideally this map should be a static one and would probably be initialized in a static initializer block. Here's how it looks in practice.

private static final Map<String, Handler> nameToHandler = new HashMap<>();

static {
    nameToHandler.put("Foo", new FooHandler());
    nameToHandler.put("Bar", new BarHandler());
}

Incidentially notice that Java static initializers are thread safe. However, if you want to ensure that the code is executed exactly once you need to make sure that the class is only loaded by a single class-loader. Static initialization is performed once per class-loader.

Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • That's pretty amazing! Thanks. But what if I have more tasks..I mean not just Foo or Boo..but Goo and Doo? :D – csirkeautomata Jan 26 '19 at 08:18
  • Can I just put an if statement like task -> {...} – csirkeautomata Jan 26 '19 at 08:20
  • @csirkeautomata Does all your `foo`, `boo` etc handlers implement a common interface? If so what is that? – Ravindra Ranwala Jan 26 '19 at 11:30
  • Stille not working.. the IDE says: no suitable method found for toMap((task)->{ [...]; } },Function,(t1,t2)->t1) method Collectors.toMap(Function super T#1,? extends K#1>,Function super T#1,? extends U#1>) is not applicable (cannot infer type-variable(s) T#1,K#1,U#1 (actual and formal argument lists differ in length)) method Collectors.toMap(Function super T#2,? extends K#2>,Function super T#2,? extends U#2>,BinaryOperator) is not applicable .... I can't really understand this.. :D – csirkeautomata Jan 26 '19 at 11:31
  • I didn't get you? – Ravindra Ranwala Jan 26 '19 at 11:32
  • Yea..they implements na interface with one method: public boolean handleTask(ToDo taskEvent); – csirkeautomata Jan 26 '19 at 11:34
  • Post the structure of your ToDO, foo, bar etc. Otherwise I have very limited capacity to assist you. – Ravindra Ranwala Jan 26 '19 at 11:34
  • Foo and Bar classes has handleTask.. this methods contains.. database operations..rmi stuffs.. and they are return true or flase..depends on the method runned successfully or not. There's no way to return null or something. My ToDo Object is an Entity.. obviously it contains Cloumns.. nothing more. It uses Lombok to generate Getter Setters etc. – csirkeautomata Jan 26 '19 at 11:38
  • @csirkeautomata What strategy you need to use to handle key conflicts? Do you want to ignore it or collect the values with the same key into a container? Which way is preferred? – Ravindra Ranwala Jan 26 '19 at 11:44
0

Then you would have only two... three entries possible in your map (true, false and null) :). Maybe it would be better to use ToDos as the keys and Boolean as the values. Then if you would want to know what was the result the method returned for given ToDo you would call result.get(someToDo)

kasptom
  • 2,363
  • 2
  • 16
  • 20