I have a task where I need to write a method which allows me to mix two generic lists and return a new mixed list.
The mixed list should have the first element of l1 at the first position of the new mixed list, the first element of the l2 should be in second position and then the second element of l1 should be in third position and so on.
If one list is longer than the other the rest should just be added in original order.
An example is: l1 = (1,2,3) and l2=(9,8) --> mixed list = (1,9,2,8,3)
public <S, T> List<T> listeMischen(List<S> l1, List<T> l2) {
List<T> newlist = new ArrayList<T>();
for(int i = 0; i < l1.size(); i++)
{
for(int j = 0; j < l2.size(); j++) {
newlist.add(charAt(i));
newlist.add(charAt(j));
}
}
return newlist;
}
P.S. I do not know how to properly add the elements as they are generic. I have typed in the absolutely wrong method of "charAt", just to showcase what I would attempt to do if the type wasn't generic but a character. Since the elements however can be generic I am very unsure of what to do.
This will return a list of a common supertype of the generic types of the two argument lists:
public <R, S extends R, T extends R> List<R> listeMischen(List<S> l1, List<T> l2) {
List<R> newList = new ArrayList<>(l1.size() + l2.size());
int sizeOfLargerList = Math.max(l1.size(), l2.size());
for (int i = 0; i < sizeOfLargerList; i++) {
if (i < l1.size())
newList.add(l1.get(i));
if (i < l2.size())
newList.add(l2.get(i));
}
return newList;
}
Usage:
public static void main(String[] args) {
List<Number> list = listeMischen(Arrays.asList(1, 2, 3), Arrays.asList(4.5, 5.5, 6.5, 7.5, 8.5));
System.out.println(list);
}
Expected output == Actual output:
[1, 4.5, 2, 5.5, 3, 6.5, 7.5, 8.5]
The following shows two overloads of the method: one for random-access lists (such as ArrayList) and another for any old iterable types, with bodies optimized for each type.
static <R> List<R> listeMischen(List<? extends R> l1, List<? extends R> l2) {
if (!(l1 instanceof RandomAccess && l2 instanceof RandomAccess))
return listeMischen((Iterable<? extends R>) l1, (Iterable<? extends R>) l2);
// Preallocate with known exact required capacity
List<R> newList = new ArrayList<>(l1.size() + l2.size());
int sizeOfSmallerList = Math.min(l1.size(), l2.size());
int i;
// Zip the lists up to common maximum index
for (i = 0; i < sizeOfSmallerList; i++) {
newList.add(l1.get(i));
newList.add(l2.get(i));
}
// Add any remaining items from one or the other list
for (; i < l1.size(); i++)
newList.add(l1.get(i));
for (; i < l2.size(); i++)
newList.add(l2.get(i));
return newList;
}
static <R> List<R> listeMischen(Iterable<? extends R> l1, Iterable<? extends R> l2) {
List<R> newList = new ArrayList<>();
Iterator<? extends R> it1 = l1.iterator();
Iterator<? extends R> it2 = l2.iterator();
// Zip the lists up to common maximum index
while (it1.hasNext() && it2.hasNext()) {
newList.add(it1.next());
newList.add(it2.next());
}
// Add any remaining items from one or the other lists
it1.forEachRemaining(newList::add);
it2.forEachRemaining(newList::add);
return newList;
}
The only sensible thing to do is return a list of Object
. Generics aren't going to help since your list is non-homogenous (and carries no guarantees, implied or explicit, of the relationship between the two object types of your list).
public List<Object> mixedList(List<?> a, List<?> b) {
List<Object> result = new ArrayList<>();
for(int i = 0, j = 0; i < a.size() && j < b.size(); i++, j++) {
result.add(a.get(i));
result.add(b.get(j));
}
return result;
}
I leave the actual issue of weaving elements in the way you prescribe as an exercise for the reader. This should satisfy the case in which both lists are the same length.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With