-2

I want to build a JSON from two lists. I need to use the corresponding elements from both lists to create a single JSON object.

My problem could be solved with ordinary loop like this:

List<Class1> items = baseManager.findObjectsByNamedQuery(Class1.class, "Class1.findAll", new Object[]{});
 for(int i=0 ; i<items.size();i++){
        List<Class2> items2 = baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCreatedBy" ,new Object[] {items.get(i).getCreatedBy()});
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        JsonObjectBuilder jpb  = Json.createObjectBuilder()
                .add("createdBy",items.get(i).getCreatedBy())
                .add("phone",items2.get(0).getPhone())             
        groupsBuilder.add(jpb);
    }

Is it possible to solve it using Java 8 Stream API?

Mistu
  • 145
  • 2
  • 13
  • 2
    Please take the time to edit your question and make it clearer. I think the fourth line in your snippet is meant to be items2.get(i)... instead of items.get(i) is that correct ? Also There is a lot of typos/missing words which make it hard to follow. "Thiking about this but" - but what ? What you want overall is probably very simple and you should get an answer in few minutes if you can make your question clear. – Jean-François Savard Jan 13 '17 at 12:47
  • 1
    You want incomplete code with lambdas? Congratulation, you already have it. – Holger Jan 13 '17 at 13:18
  • I edited your question to make it sound more clear. Please check whether I did not alter the meaning of your question. Check the answers [here](http://stackoverflow.com/q/30144661/4856258): seems that it's what you want. – Tagir Valeev Jan 13 '17 at 14:16
  • I was there. it's not quite enough. I should to use an element from first loop in SQL and after That add it to JSON. – Mistu Jan 13 '17 at 14:31
  • What is the relevance of the unused `SimpleDateFormat` that you re-instantiate in every loop iteration? A talisman? – Holger Jan 13 '17 at 15:54
  • I used it in other gets when is calendar used . – Mistu Jan 13 '17 at 21:52

3 Answers3

1

There are still some things unclear. Like why you are insisting on creating that SimpleDateFormat instance that you are not using anywhere. Or whether there is a significance in calling getCreatedBy() multiple times. Assuming that it is not necessary, the following code is equivalent

baseManager.findObjectsByNamedQuery(Class1.class, "Class1.findAll", new Object[]{})
    .stream()
    .map(item -> item.getCreatedBy())
    .map(createdBy -> Json.createObjectBuilder()
        .add("createdBy", createdBy)
        .add("phone", baseManager.findObjectsByNamedQuery(
            Class2.class, "Class2.findByCreatedBy", new Object[] {createdBy})
            .get(0).getPhone())
    )
    .forEach(jpb -> groupsBuilder.add(jpb));

It’s still unclear to me whether (or why) findObjectsByNamedQuery is not a varargs method. It would be quite natural to be a varargs method, not requiring these explicit new Object[] { … } allocations.

Holger
  • 285,553
  • 42
  • 434
  • 765
0

With pure Java8 Stream API:

public void convertItemsToJSon(List<Item> items) {
    ...
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    Map<Item, List<Class2>> sqlItems = items
            .stream()
            .collect(Collectors.toMap(Function.identity(), (item) -> baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCratedBy", new Object[]{item.getCreatedBy()})));

    sqlItems.entrySet()
            .stream()
            .map(sqlItem -> buildJson(sqlItem.getKey(), sqlItem.getValue()))
            .forEach(groupsBuilder::add);
    ...
}

private JsonObjectBuilder buildJson(Item item,  List<Class2> class2Items) {
    return Json.createObjectBuilder().add("createdBy", item.getCreatedBy());
}

With StreamEx library

public void convertItemsToJSonStreamEx(List<Item> items) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    ...
    StreamEx.of(items)
            .cross(item -> baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCratedBy", new Object[]{item.getCreatedBy()}).stream())
            .mapKeys(item -> Json.createObjectBuilder().add("createdBy", item.getCreatedBy()))
            .mapKeyValue(this::addField)
            .forEach(groupsBuilder::add);
    ...
}

private JsonObjectBuilder addField(JsonObjectBuilder json, Class2 class2) {
    // You logic how to convert class2 to field in JSON
    return json;
}
Vlad Bochenin
  • 3,007
  • 1
  • 20
  • 33
  • It is not list of lists it is 2 list from 2 SQL --> 1 JSON. List<>... for(i...){ 2 List on element form list 1 } how to add it 2 list items .stream() .map(item -> Json.createObjectBuilder().add("createdBy",item.getCreatedBy().add("telefon",items2.get(0).get...()))) .forEach(groupsBuilder::add); Like this – Mistu Jan 13 '17 at 12:34
  • 1
    I guess, the OP wants zip. Something like `EntryStream.zip(items2, items3).mapKeyValue((item2, item3) -> Json.blahblah).forEach(groupsBuilder::add)` with StreamEx. – Tagir Valeev Jan 13 '17 at 13:49
  • @TagirValeev initial version of question is totally different from final version )) – Vlad Bochenin Jan 13 '17 at 14:59
  • Sorry your first sugestiom was the best look at my working code. U are realy help me . – Mistu Jan 13 '17 at 21:54
0

Thanks for your help and solution. Most helpful was the first response from Vlad Bochenin The code is here:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    items.stream().map(item -> {
        List<Class2> items2 = baseManager.findObjectsByNamedQuery(Class2.class, "Class2.findByCreatedBy", new Object[]{item.getCreatedBy()});
        JsonObjectBuilder jpb = Json.createObjectBuilder()
                .add("createdBy", item.getCreatedBy())
                .add("phone", items2.get(0).getPhone())
                return jpb;
    }).forEach(groupsBuilder::add);
Mistu
  • 145
  • 2
  • 13