0

Lets say I have a list with objects, lets call it listA which is unordered, and it has objects of type A. type A has a field called name. now, I have another list, which is ordered. let's call it listB and it is ordered. the objects in this list are of type B and they also had a field name.

Now, I want listA to be ordered as listB, and the only thing that is the same in those two lists is the field name which is the same in both objects.

what is the most efficient way to do so?

8
  • 2
    there is some logical leak in this example: what happens, for example, if a given name is present in listA but not in listB, or viceversa? Commented Aug 30, 2018 at 8:37
  • What if your second list is sorted by an attribute different from name? Is that possible? Commented Aug 30, 2018 at 8:37
  • Can you define "most efficient"? Do you need the sort operation to happen fast, or using little memory, for example? Will sorting happen frequently? Do you anticipate lots of additions and removals from the lists, or will they only be built once and not changed? For example - might it be quicker to maintain the list in order, and identify the correct place to insert each new item as its added, rather than sorting the entire thing? Commented Aug 30, 2018 at 8:42
  • 1
    Generate proxy list, which holds a value to the second list, whose position in the list is the same as the first (ie proxy.get(0) will return the index of the object in the second list which matches the first), from this you can then determine how the second list should be ordered Commented Aug 30, 2018 at 8:43
  • @Leviand it cannot be. if something in listA then it will have a match in listB. Commented Aug 30, 2018 at 12:39

1 Answer 1

1

I hope I'm understanding your problem.

Is the field 'name' a common field shared by the two types of Object (A and B)? In other words, do the two types (A and B) extend the same Class C that contains the field 'name'? If so you could implement the Comparable in Class C and then Collections.sort() would do the trick for you. All you have to do, while implementing the comparable, would be to 'teach' it how to compare the field 'name' so that it orders, in the same manner, the list of type B objects, you specify, are ordered.

Another way to do this, in case your classes don't have anything in common, therefore not making sense of having a superclass C, would be to create a Comparator interface, where you could specify the fields that can be used to compare two distinct objects and then do the sorting using those fields, in other words:

  1. Create a Interface with the method getCompareFields() returns String[]; (for example)
  2. Implement interface of point 1. in objects A and B
  3. Implement a sorting algorithm that uses this interface's getCompareFields() method for sorting.

And, another way even, for you to do this, but, in my opinion, would be more complicated, would be to use reflection to get the field 'name' of both objects, in case they are not related in any kind.

I hope this helps you.

EDIT Example of reflection:

Class TypeA (Example)

public class TypeA {
private String name;
private String id;

public TypeA() {
    this(null, null);
}

public TypeA(String name, String id) {
    this.name = name;
    this.id = id;
}

public String getName() {
    return this.name;
}

public String getId() {
    return this.id;
}

@Override
public String toString() {
    return "(" + name + ", " + id + ")";
}

}

Class TypeB (Example)

public class TypeB {
private String name;
private List<Integer> numbers;

public TypeB() {
    this(null);
}

public TypeB(String name, int ... numbers) {
    this.name = name;

    this.numbers = new LinkedList<Integer>();
    if (numbers != null) {
        for (int i : numbers) {
            this.numbers.add(i);
        }
    }
}

public String getName() {
    return this.name;
}

public List<Integer> getANumber() {
    return this.numbers;
}

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append("(").append(name).append(", [");

    Iterator<Integer> i = this.numbers.iterator();

    if (i.hasNext()) {
        builder.append(i.next());

        while (i.hasNext()) {
            builder.append(", ").append(i.next());
        }
    }

    builder.append("])");
    return builder.toString();
}

}

Reflection Name Comparator:

public class NameReflectionComparator implements Comparator<Object> {

@Override
public int compare(Object o1, Object o2) {
    if (o1 != null && o2 != null) {
        try {
            Method obj1_getNameMethod = o1.getClass().getMethod("getName");
            Method obj2_getNameMethod = o2.getClass().getMethod("getName");

            String obj1_name = (String) obj1_getNameMethod.invoke(o1);
            String obj2_name = (String) obj2_getNameMethod.invoke(o2);

            if (obj1_name != null) {
                return obj1_name.compareTo(obj2_name);
            } else if (obj2_name != null) {
                return obj2_name.compareTo(obj1_name);
            }
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }

    } else if (o1 != null && o2 == null) {
        return 1;
    } else if (o1 == null && o2 != null) {
        return -1;
    }

    return 0;
}

}

Main:

public class Main {
public static void main(String[] args) {

    // both TypeA and TypeB have field name and method getName()
    // unsorted list
    List<TypeA> typeAList = new LinkedList<TypeA>();
    typeAList.add(new TypeA("Yves Larock", UUID.randomUUID().toString()));
    typeAList.add(new TypeA("I'm ok", UUID.randomUUID().toString()));
    typeAList.add(new TypeA("Aaah", UUID.randomUUID().toString()));
    typeAList.add(new TypeA("Noooh", UUID.randomUUID().toString()));

    // sorted list
    List<TypeB> typeBList = new LinkedList<TypeB>();
    typeBList.add(new TypeB("Aaah", 1, 2, 3));
    typeBList.add(new TypeB("I'm ok", 1));
    typeBList.add(new TypeB("Noooh", 34, 3));
    typeBList.add(new TypeB("Yves Larock", 4, 5, 3, 9));

    System.out.println("ListA:\n" + typeAList);
    System.out.println("ListB:\n" + typeBList);

    NameReflectionComparator comparator = new NameReflectionComparator();
    Collections.sort(typeAList, comparator);


    System.out.println("=== AFTER SORT ====\nListA:\n" + typeAList);
    System.out.println("ListB:\n" + typeBList);
}

}

Result:

ListA: [(Yves Larock, f40cb523-58e8-4ee2-aa4f-991ce7e7cdd5), (I'm ok, 5a66b9d9-7a27-4529-ab64-c893291bd9b0), (Aaah, 4842fd55-47e5-48ac-b7b6-ebc7acf7023c), (Noooh, 8dc89675-bc28-4374-aff2-0c5d0ae6dd9d)]

ListB: [(Aaah, [1, 2, 3]), (I'm ok, 1), (Noooh, [34, 3]), (Yves Larock, [4, 5, 3, 9])]

=== AFTER SORT ==== ListA: [(Aaah, 4842fd55-47e5-48ac-b7b6-ebc7acf7023c), (I'm ok, 5a66b9d9-7a27-4529-ab64-c893291bd9b0), (Noooh, 8dc89675-bc28-4374-aff2-0c5d0ae6dd9d), (Yves Larock, f40cb523-58e8-4ee2-aa4f-991ce7e7cdd5)]

ListB: [(Aaah, [1, 2, 3]), (I'm ok, 1), (Noooh, [34, 3]), (Yves Larock, [4, 5, 3, 9])]

Sign up to request clarification or add additional context in comments.

4 Comments

they do not extends the same class. they are completely different, except they both have a fields called name which is the same values. so how can it be done with the reflection that you said? can you show an example?
thank you for the detailed example. how is it in performence? is it going to be sorted in O(n^2)? is it the best we can get or can it be done faster?
It depends on the type of sorting algorithm. Quoting from Collections.sort(): "(..) iterative mergesort that requires far fewer than n lg(n) comparisons when the input array is partially sorted, while offering the performance of a traditional mergesort when the input array is randomly ordered. If the input array is nearly sorted, the implementation requires approximately n comparisons. Temporary storage requirements vary from a small constant for nearly sorted input arrays to n/2 object references for randomly ordered input arrays." Then there's the penalty for using reflection itself.
but I tested your code, and it is beeing sorted just by ABC and it has nothing to do with the way that listB is sorted. you didn't used listB in any wat during the compartion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.