HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavaMinor

Merge two lists in Java and sort them using Object property and another condition

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
conditionmergejavatwopropertyusinganotherlistsandsort

Problem

I have two lists List list1 = new ArrayList(), list2 = new ArrayList(); (Not the same size), of the class Person:

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Person{" + "name=" + name + ", age=" + age + '}';
    }

}


I want to create a new list using list1 and list2 sorted by age (descending), but I also another condition that is better explained with an example:

//L1 = from list1, L2 = from list2
//looping trough the new list
Person{name=Alec L1, age=75}
Person{name=Menard L1, age=50} //Bob should be here
Person{name=Bob L2, age=50}


He should, because his age is equal to Menard, Alec is from L1 and two Person from L1 can't be one after another is this kind of situation happens.

A complete list should look like this:

Person{name=Giant L2, age=100}
Person{name=Derp L1, age=50}
Person{name=John L2, age=50}
Person{name=Menard L1, age=44}
Person{name=Lili L2, age=44}
Person{name=Lili L1, age=44}
Person{name=Menard L2, age=44}
Person{name=Bob L1, age=22}
Person{name=Alec L2, age=21}
Person{name=Alec L1, age=21}
Person{name=Herp L2, age=21}
Person{name=Herp L1, age=21}
Person{name=Alice L1, age=12}
Person{name=Little L2, age=5}


Here is my complete code to achieve this result:

```
List list1 = new ArrayList(), list2 = new ArrayList();

list1.add(new Person("Derp L1", 50));
list1.add(new Person("Alec L1", 21));
list1.add(new Person("Herp L1", 21));
list1.add(new Person("Menard L1", 44));
list1.add(new Person("Lili L1", 44));
list1.add(new Person("Alice L1", 12));
list1.add(new Person("Bob L1", 22));

Collections.sort(list1, new Comparator() {
@Override
public int compare(final Person object1, f

Solution

Your problem statement is not very clear. As I understand it, you want to have a combined sorted list but interleave elements from list1 and list2 whenever the age is the same.

Here's a simple implementation of that logic. I used java 8 streams to sort lists and put them in ArrayDeques.

import static java.util.stream.Collectors.toCollection;
import static java.util.Comparator.comparingInt;

static List interleaveSort(List list1, List list2, Comparator cmp) {
    // sort the lists and set them up as queues
    Deque x = list1.stream().sorted(cmp).collect(toCollection(ArrayDeque::new));
    Deque y = list2.stream().sorted(cmp).collect(toCollection(ArrayDeque::new));

    List result = new ArrayList<>(x.size() + y.size());

    while (!x.isEmpty() && !y.isEmpty()) {
        if (cmp.compare(x.peek(), y.peek()) > 0) {
            result.add(y.poll());
        } else {
            // whenever we pick from X, swap queues so next time we will favor the other list
            result.add(x.poll());
            Deque t = x;
            x = y;
            y = t;
        }
    }
    // since the while loop terminates when one of the queues is empty
    // we should add the left-over elements
    result.addAll(x);
    result.addAll(y);

    return result;
}


Then, in your main method:

List allList=interleaveSort(list1, list2, comparing(Person::getAge).reversed());

Code Snippets

import static java.util.stream.Collectors.toCollection;
import static java.util.Comparator.comparingInt;

static<T> List<T> interleaveSort(List<T> list1, List<T> list2, Comparator<T> cmp) {
    // sort the lists and set them up as queues
    Deque<T> x = list1.stream().sorted(cmp).collect(toCollection(ArrayDeque::new));
    Deque<T> y = list2.stream().sorted(cmp).collect(toCollection(ArrayDeque::new));

    List<T> result = new ArrayList<>(x.size() + y.size());

    while (!x.isEmpty() && !y.isEmpty()) {
        if (cmp.compare(x.peek(), y.peek()) > 0) {
            result.add(y.poll());
        } else {
            // whenever we pick from X, swap queues so next time we will favor the other list
            result.add(x.poll());
            Deque<T> t = x;
            x = y;
            y = t;
        }
    }
    // since the while loop terminates when one of the queues is empty
    // we should add the left-over elements
    result.addAll(x);
    result.addAll(y);

    return result;
}
List<Person> allList=interleaveSort(list1, list2, comparing(Person::getAge).reversed());

Context

StackExchange Code Review Q#100973, answer score: 3

Revisions (0)

No revisions yet.