5
\$\begingroup\$

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?

asked Aug 14, 2015 at 20:11
\$\endgroup\$
4
  • 1
    \$\begingroup\$ What happens if you have in List1, 50, 40 30 , and in List2 50 45 42? \$\endgroup\$ Commented Aug 14, 2015 at 21:16
  • \$\begingroup\$ L1-50 first, L2-50 next, then, L2-45, L2-42, L1-40 and L1-30 \$\endgroup\$ Commented Aug 15, 2015 at 5:25
  • \$\begingroup\$ And yet you have Person{name=Herp L1, age=21} followed by Person{name=Alice L1, age=12} in your expected list... care to update? \$\endgroup\$ Commented Aug 15, 2015 at 7:19
  • \$\begingroup\$ I fail to see where the problem is. 12 is less than 21 and no one from L2 is in between. \$\endgroup\$ Commented Aug 18, 2015 at 19:26

2 Answers 2

3
\$\begingroup\$

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<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());
answered Aug 15, 2015 at 7:19
\$\endgroup\$
3
  • \$\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\$ Commented 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\$ Commented Aug 18, 2015 at 19:16
  • \$\begingroup\$ Sorry, that was my typo. I did a static include of comparingInt but used comparing. static include is right and the code is wrong. It's actually better to do comparingInt(Person::getAge) \$\endgroup\$ Commented Aug 18, 2015 at 19:21
-1
\$\begingroup\$

You can do list1.addAll(list2) and then sort list1 which now contains both lists

Vogel612
25.5k7 gold badges59 silver badges141 bronze badges
answered Aug 14, 2015 at 20:20
\$\endgroup\$
4
  • \$\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\$ Commented Aug 14, 2015 at 20:25
  • \$\begingroup\$ not if you call the sort after merging the list as suggested here \$\endgroup\$ Commented Aug 14, 2015 at 20:27
  • \$\begingroup\$ I don't know if it is only me, but doing : list1.addAll(list2); then Collections.sort(list1, (final Person object1, final Person object2) -> object2.getAge()-object1.getAge()); give me the same result as my previous comment \$\endgroup\$ Commented 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\$ Commented Aug 14, 2015 at 21:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.