Recently had someone ask me to solve this problem: assume you have a list of objects, some of which may be lists of arbitrary depths. Write a function to return the list “flattened,” so sublists are all in the “main” list. I solved it recursively pretty easily, but it took some thought to do it without recursion. My solutions are below.
package com.evanhoffman.listflattener;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
public class ListFlattener {
private static Logger logger = Logger.getLogger(ListFlattener.class);
public static List flattenList(List inList) {
List newList = new LinkedList();
for (Object i : inList) {
// If it's not a list, just add it to the return list.
if (!(i instanceof List)) {
newList.add(i);
} else {
// It's a list, so add each item to the return list.
newList.addAll(flattenList((List)i));
}
}
return newList;
}
public static List flattenListNoRecursion(List inList) {
List tempList = null;
// Clone the input list to newList
List newList = new LinkedList();
newList.addAll(inList);
ListIterator iterator = newList.listIterator();
int currentPosition = 0;
while (iterator.hasNext()) {
Object i = iterator.next();
if (!(i instanceof List)) {
// If it's not a list, advance the position. Don't advance position if this IS a list.
currentPosition++;
} else {
// If the current item is a list, save it to a temp var.
tempList = (List) i;
// Delete the list from the list
iterator.remove();
// Add each item from the temp list to the master list at the same position the sublist was removed.
for (Object obj : tempList) {
iterator.add(obj);
}
// reset the iterator to re-walk the list that was just inserted (within the master) to check for more lists.
iterator = newList.listIterator(currentPosition);
}
}
return newList;
}
public static void printList(List list) {
int i = 0;
for (Object item : list) {
logger.debug("List item #"+i +": "+item);
i++;
}
}
public static void main(String[] args) {
BasicConfigurator.configure();
// List of strings
LinkedList stringList = new LinkedList();
for (Integer i = 0; i < 10; i++) {
stringList.add("String #" +i.toString());
}
// List of integers
LinkedList intList = new LinkedList();
for (Integer i = 10; i < 20; i++) {
intList.add(i);
}
// Nested Lists
LinkedList nestedList1 = new LinkedList();
LinkedList nestedList2 = new LinkedList();
LinkedList nestedList3 = new LinkedList();
nestedList3.add("Nested String 1");
nestedList3.add("Nested String 2");
nestedList2.add(nestedList3);
nestedList1.add(nestedList2);
LinkedList bigList = new LinkedList();
bigList.add("First item");
bigList.add(stringList);
bigList.add("Third Item");
bigList.add(intList);
bigList.add("Fifth Item");
bigList.add(nestedList1);
bigList.add("Seventh Item");
// List flattenedList = flattenList(bigList);
List flattenedListRecursion = flattenList(bigList);
List flattenedList = flattenListNoRecursion(bigList);
logger.debug("Original list: "+bigList.toString());
// printList(bigList);
logger.debug("Flattened list (w/ recursion): "+flattenedListRecursion.toString());
logger.debug("Flattened list (no recursion): "+flattenedList.toString());
// printList(flattenedList);
}
}
Leave a comment