I have two lists List<Person> 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<Person> 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<Person>() {
@Override
public int compare(final Person object1, final Person object2) {
return object2.getAge()-object1.getAge();
}
});
list2.add(new Person("Little L2", 5));
list2.add(new Person("Lili L2", 44));
list2.add(new Person("Alec L2", 21));
list2.add(new Person("Herp L2", 21));
list2.add(new Person("Menard L2", 44));
list2.add(new Person("Giant L2", 100));
list2.add(new Person("John L2", 50));
Collections.sort(list2, new Comparator<Person>() {
@Override
public int compare(final Person object1, final Person object2) {
return object2.getAge()-object1.getAge();
}
});
List<Person> allList = new ArrayList();
int l1 = 0, l2 = 0;
for (int i = 0; i < list1.size()+list2.size(); i++)
if (l1 < list1.size() && l2 < list2.size())
if (list1.get(l1).getAge() > list2.get(l2).getAge())
allList.add(list1.get(l1++));
else if (list1.get(l1).getAge() < list2.get(l2).getAge())
allList.add(list2.get(l2++));
else if (allList.size() > 0)
{
if (list1.get(l1).getName().contains("L1") == allList.get(allList.size()-1).getName().contains("L1"))
allList.add(list2.get(l2++));
else
allList.add(list1.get(l1++));
}
else
allList.add(list1.get(l1++));
else if (list1.size() == l1)
allList.add(list2.get(l2++));
else
allList.add(list1.get(l1++));
for (Person person : allList)
System.out.println(person.toString());
But, is there another way to do it? More elegant code or using some built in Java class?
2 Answers 2
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 ArrayDeque
s.
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;
}
Then, in your main method:
List<Person> allList=interleaveSort(list1, list2, comparing(Person::getAge).reversed());
-
\$\begingroup\$ Thanks for your answer, but I get: invalid method reference: "non-static method getAge() cannot be referenced from a static context" when I call interleaveSort. \$\endgroup\$varnaud– varnaud2015年08月18日 16:20:19 +00:00Commented Aug 18, 2015 at 16:20
-
\$\begingroup\$ I had to do :
List<Person> combo = interleaveSort(list1, list2, Comparator.comparing(Person::getAge).reversed());
and then your code worked. \$\endgroup\$varnaud– varnaud2015年08月18日 19:16:56 +00:00Commented Aug 18, 2015 at 19:16 -
\$\begingroup\$ Sorry, that was my typo. I did a static include of
comparingInt
but usedcomparing
. static include is right and the code is wrong. It's actually better to docomparingInt(Person::getAge)
\$\endgroup\$Misha– Misha2015年08月18日 19:21:11 +00:00Commented Aug 18, 2015 at 19:21
You can do list1.addAll(list2)
and then sort list1
which now contains both lists
-
\$\begingroup\$ If you try your proposed code, it would give something 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 L1, age=44} Person{name=Lili L2, age=44} Person{name=Menard L2, age=44} Person{name=Bob L1, age=22} Person{name=Alec L1, age=21} Person{name=Herp L1, age=21} Person{name=Alec L2, age=21} Person{name=Herp L2, age=21} Person{name=Alice L1, age=12} Person{name=Little L2, age=5} And it's not what I'm looking for. \$\endgroup\$varnaud– varnaud2015年08月14日 20:25:49 +00:00Commented Aug 14, 2015 at 20:25
-
\$\begingroup\$ not if you call the sort after merging the list as suggested here \$\endgroup\$Vogel612– Vogel6122015年08月14日 20:27:22 +00:00Commented Aug 14, 2015 at 20:27
-
\$\begingroup\$ I don't know if it is only me, but doing :
list1.addAll(list2);
thenCollections.sort(list1, (final Person object1, final Person object2) -> object2.getAge()-object1.getAge());
give me the same result as my previous comment \$\endgroup\$varnaud– varnaud2015年08月14日 20:39:35 +00:00Commented Aug 14, 2015 at 20:39 -
\$\begingroup\$ Please add some more context to your post. For example, explain why your solution is better, explain the reasoning behind your solution, etc. \$\endgroup\$SirPython– SirPython2015年08月14日 21:25:31 +00:00Commented Aug 14, 2015 at 21:25
Person{name=Herp L1, age=21}
followed byPerson{name=Alice L1, age=12}
in your expected list... care to update? \$\endgroup\$