1
\$\begingroup\$

I am using Java 8. I want to build a final list using following data. All objects in basicData list must be added to final list. But if there is a matching object based on matching key from modData map with the basicData's id & isMod set to true, I want to add that object to the final list instead of basic. For example modData's b_mod's key matches the id for an object in basicData list. I want to add the modData's object instead to final list in this case. Not only that, if I make a switch, that object goes up in order in the final list.

Another scenario where the key and id matches but isMod is set to false. In this case, I will add the object from basicData and the object has to go up in order too.

If there is no match at all then just add basic data's object.

based on data above the final list should have following objects in following order:

[b_mod, e_mod, d, a, c]

A quick recap on criteria. b_mod and e_mod are at top cos they matched key to ids and also isMod set to true. d comes next cos it matched too but isMod was set to false. In this case we used the object from the basicData list but it goes up in order. no match for a and c so just added behind. f_mod was not added at all cos it doesn't exist in basicData list.

Note that I can't override equals method. There is already an override (this obj has a lot more fields) with a different logic for another purpose.

I could do nested for loops or like 3 separate for loops to get this done which all works. But they seem so inefficient.

This is my solution which I believe is extremely inefficient. Please advice.

import java.util.*;

public class DataSorter {
    public static void main(String[] args) {
        List<Data> basicData = new ArrayList<>(); // isMod always false for this list items
        basicData.add(new Data("100", "a", false));
        basicData.add(new Data("200", "b", false));
        basicData.add(new Data("300", "c", false));
        basicData.add(new Data("400", "d", false));
        basicData.add(new Data("500", "e", false));

        Map<String, Data> modData = new LinkedHashMap<>();
        modData.put("200", new Data("200", "b_mod", true)); // match. add this instead and move up the order.
        modData.put("400", new Data("400", "d_mod", false)); // is a match but isMod set to false. Thus still adding obj from basicData.
        modData.put("500", new Data("500", "e_mod", true)); // match. add this instead and move up the order.
        modData.put("600", new Data("600", "f_mod", true)); // this is not in basicData so not added to final list.

        //start solution

        //adding just matching data which is also set isMod to true
        List<Data> finalData = new ArrayList<>();
        for(Data d : basicData){
            Data modObj = modData.get(d.getId());
            if(modObj != null){
                if (modObj.isMod()){
                    finalData.add(modObj);
                }
            }
        }

        //adding basic objects when there was a match but isMod was false at modData map.
        for(Data d : basicData){
            Data modObj = modData.get(d.getId());
            if(modObj != null){
                if (!modObj.isMod()){
                    finalData.add(modObj);
                }
            }
        }

        //adding remaining objects from basicData list.
        for (Data basicDatum : basicData) {
            boolean dataExists = false;
            Data obj = null;
            for (Data finalDatum : finalData) {
                obj = basicDatum;
                if (obj.getId().equals(finalDatum.getId())) {
                    dataExists = true;
                    break;
                }
            }
            if (!dataExists) {
                finalData.add(obj);
            }
        }
        // end solution

        // printing to test it
        for(Data d : finalData){
            System.out.println(d);
            System.out.println("===============");
        }
    }

}

class Data {
    private String id;
    private String name;
    private boolean isMod;

    Data(String id, String name, boolean isMod) {
        this.id = id;
        this.name = name;
        this.isMod = isMod;
    }

    String getId() {
        return id;
    }

    boolean isMod() {
        return isMod;
    }

    @Override
    public String toString() {
        return "Data{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", isMod=" + isMod +
                '}';
    }
}
\$\endgroup\$
2
\$\begingroup\$

Consider having 3 lists. One of modObj != null && modObj.isMod(). Another one of modObj != null && !modObj.isMod(). Third one of the rest (aka modObj == null). Finally join them. E.g.:

    List<Data> front_list = new ArrayList<>();
    List<Data> mid_list = new ArrayList<>();
    List<Data> tail_list = new ArrayList<>();

    for (Data d: basicData) {
        Data modObj = modData.get(d.getId());
        if (modObj == null) {
            tail_list.add(d);
        } else if (modObj.isMod()) {
            front_list.add(modObj);
        } else {
            mid_list.add(modObj);
        }
    }
\$\endgroup\$
  • \$\begingroup\$ I think you mean tail_list.add(d), not .append(d). Ditto for the others. \$\endgroup\$ – AJNeufeld Jan 28 at 4:33
  • \$\begingroup\$ Minor efficiency improvement: use new ArrayList<>(basicData.size()) to preallocate enough room for all of the data. \$\endgroup\$ – AJNeufeld Jan 28 at 4:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.