简体   繁体   中英

Iterate and combine two sorted arraylists of different objects

My situation is like this: I have two arraylists with different types of objects. Each object has a field name and a field date ArrayList events, ArrayList things . I sorted the arraylists by name, and if the name is the same, sorted them by date.

Lets say that ArrayList1 has the following objects : event1 01.12, event1 05.12, event2 04.03, event3 05.05

And ArrayList2 has: event0 02.01, event2 05.10

Now I want to make a TableRow containing a textview with an Event name and another textview with the dates for it. So my table layout will be like this:

Event0    02.11(from2)
Event1    01.12(from1), 05.12(from1)
Event2    02.01(from2), 04.03(from1)
Event3    05.10(from1)

How can I iterate through the 2 arraylists and get each unique event and all the dates for it to show in a TableRow?

I sort them like this

Collections.sort(alist, new Comparator<Object1>() {
                @Override
                public int compare(Object1 a1, Object1 a2) {
                    SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
                    Date date1;
                    Date date2;
                    if(a1.name.equals(a2.name)) {
                        try {
                            date1 = format.parse(a1.date);
                            date2 = format.parse(a2.date);
                        } catch (ParseException e) {
                            throw new IllegalArgumentException("Could not parse date!", e);
                        }
                        return date1.compareTo(date2);
                    }

                    else
                        return a1.name.compareTo(a2.name) ;
                }

            });

The best way would be to have the different types of objects inherit from the same class/ implement the same interface. If this is not possible, try the following:

    List<Object> combinedList = new ArrayList<>();
    combinedList.addAll(array1);
    combinedList.addAll(array2);
    Collections.sort(combinedList, new Comparator<Object>() {
        public int compare(Object o1, Object o2) {
            String name1 = o1 instanceof Type1 ? ((Type1) o1).getName()
                    : ((Type2) o1).getName();
            String name2 = o2 instanceof Type1 ? ((Type1) o2).getName()
                    : ((Type2) o2).getName();

            Date date1 = o1 instanceof Type1 ? ((Type1) o1).getDate()
                    : ((Type2) o1).getDate(); 
            Date date2 = o2 instanceof Type1 ? ((Type1) o2).getDate()
                    : ((Type2) o2).getDate(); 
            int comparedNames = name1.compareTo(name2);
            return comparedEvents != 0 ? comparedEvents : date1.compareTo(date2);
        }
    });

Consider creating an adapter class to wrap instances of your original objects, sort the wrapped objects, then extract the original objects from the wrapper. For example, if FirstThingy and SecondThing represent your original object classes with no common inheritance or interface:

public class FirstThingy {
    private String name;
    private java.util.Date date;
    private double value;

    public FirstThingy(String aName, java.util.Date aDate, double aValue) {
        this.name = aName;
        this.date = aDate;
        this.value = aValue;
    }

    public String getName() { return this.name; }
    public java.util.Date getDate() { return this.date; }
    public double getValue() { return value; }

    @Override 
    public String toString() {
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("MM/dd/yyyy");
        return String.format("%s(name = \"%s\", date = \"%s\", value = %s)",
                             getClass().getSimpleName(),
                             getName(),
                             sdf.format(getDate()),
                             Double.toString(getValue()));
    }
}


public class SecondThingy {
    private String name;
    private java.util.Date date;
    private String email;

    public SecondThingy(String aName, java.util.Date aDate, String anEmail) {
        this.name = aName;
        this.date = aDate;
        this.email = anEmail;
    }

    public String getName() { return this.name; }
    public java.util.Date getDate() { return this.date; }
    public String getEmail() { return email; }

    @Override 
    public String toString() {
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("MM/dd/yyyy");
        return String.format("%s(name = \"%s\", date = \"%s\", value = %s)",
                             getClass().getSimpleName(),
                             getName(),
                             sdf.format(getDate()),
                             getEmail());
    }
}

Create an adapter class to wrap the original instances:

public abstract class ThingyAdapter<T> implements Comparable<ThingyAdapter> {
    abstract public String getName();
    abstract public java.util.Date getDate();
    abstract public T getThingy();

    public static ThingyAdapter<FirstThingy> newAdapter(FirstThingy thingy) { return new FirstAdapter(thingy); }
    public static ThingyAdapter<SecondThingy> newAdapter(SecondThingy thingy) { return new SecondAdapter(thingy); }

    @Override
    public int compareTo(ThingyAdapter adapter) {
        if (adapter == null) { return 1; }
        if (this == adapter) { return 0; }
        int comparison = getName().compareTo(adapter.getName());
        if (comparison == 0) { return getDate().compareTo(adapter.getDate()); }
        return comparison;
    }

    @Override public String toString() { return getThingy().toString(); }
}

Now implement the wrapper for each of the original classes:

public class FirstAdapter extends ThingyAdapter<FirstThingy> {
    private final FirstThingy thingy;

    public FirstAdapter(FirstThingy thingy) { this.thingy = thingy; }
    @Override public String getName() { return this.thingy.getName(); }
    @Override public java.util.Date getDate() { return this.thingy.getDate(); }
    @Override public FirstThingy getThingy() { return this.thingy; }
}

public class SecondAdapter extends ThingyAdapter<SecondThingy> {
    private final SecondThingy thingy;

    public SecondAdapter(SecondThingy thingy) { this.thingy = thingy; }
    @Override public String getName() { return this.thingy.getName(); }
    @Override public java.util.Date getDate() { return this.thingy.getDate(); }
    @Override public SecondThingy getThingy() { return this.thingy; }
}

Then your program's implementation of merging the lists, sorting, then processing the results might look like:

public class MixedLists {

    private static java.util.Date date(int year, int month, int day) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.set(year, month, day);
        return calendar.getTime();
    }

    public static void main(String[] args) {
        int status = 0;

        try {
            FirstThingy[] firstArray = {
                new FirstThingy("Thomas", date(1964,9,30), 10.5d),
                new FirstThingy("George", date(1970, 1, 12), 16.1d),
                new FirstThingy("Conrad", date(2001, 5, 10), 34.1d),
                new FirstThingy("Fred", date(1980, 9, 22), 25.3d),
                new FirstThingy("George", date(1970, 1, 12), 19.9d)
            };

            SecondThingy[] secondArray = {
                new SecondThingy("Karl", date(1964,9,30), "karl@host.com"),
                new SecondThingy("Fred", date(1990, 6, 15), "fredrick@host.com"),
                new SecondThingy("Paul", date(1970, 1, 12), "paul@host.com"),
                new SecondThingy("Fred", date(1970, 1, 12), "fred@host.com"),
                new SecondThingy("Conrad", date(2001, 5, 10), "conrad@host.com")
            };

            java.util.ArrayList<ThingyAdapter> list = new java.util.ArrayList<ThingyAdapter>();
            for(FirstThingy thingy : firstArray) {
                list.add(ThingyAdapter.newAdapter(thingy));
            }

            for(SecondThingy thingy : secondArray) {
                list.add(ThingyAdapter.newAdapter(thingy));
            }

            java.util.Collections.sort(list);
            for(ThingyAdapter thingy : list) {
                System.out.println(thingy.toString());
            }
        } catch (Throwable thrown) {
            status = -1;
            thrown.printStackTrace(System.out);
        } finally {
            System.exit(status);
        }
    }
}

The results of execution:

FirstThingy(name = "Conrad", date = "06/10/2001", value = 34.1)
SecondThingy(name = "Conrad", date = "06/10/2001", value = conrad@host.com)
SecondThingy(name = "Fred", date = "02/12/1970", value = fred@host.com)
FirstThingy(name = "Fred", date = "10/22/1980", value = 25.3)
SecondThingy(name = "Fred", date = "07/15/1990", value = fredrick@host.com)
FirstThingy(name = "George", date = "02/12/1970", value = 16.1)
FirstThingy(name = "George", date = "02/12/1970", value = 19.9)
SecondThingy(name = "Karl", date = "10/30/1964", value = karl@host.com)
SecondThingy(name = "Paul", date = "02/12/1970", value = paul@host.com)
FirstThingy(name = "Thomas", date = "10/30/1964", value = 10.5)

As far ai understood i think the best solution for you is to use a single list which can contain differnt objects but with the same parent class. I will explain better. Since all your objects have a field name and date in common, so you can do like this:

public class CommonBaseClass {
    public String name;
    public long date;
}

Then you can extend this object as many times as you want for example:

public class MyEvent extends CommonBaseClass {
    public String actor;
    public String city;
}

public class MyEvent2 extends CommonBaseClass {
    public String type;
    public int nemberOfFriends;
}

Now you can create an list like this and add both MyEvent and MyEvent2 objects:

ArrayList<CommonBaseClass> myList = new ArrayList<CommonBaseClass>();
myList.add(new MyEvent("myEvent", "Rome"));
myList.add(new MyEvent2("Concert", 10));

From now on you can threat myList as a list of CommonBaseClass objects and sort them as you did before.

Update When you want to retrieve your objects from list you can do like this:

if(myList.get(index) instanceof MyEvent) {
    MyEvent event = ((MyEvent) myList.get(index));
    .....do something with it......
}else {
    MyEvent2 event = ((MyEvent2) myList.get(index));
    .....do something with it......
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM