Tapas Bose
Tapas Bose

Reputation: 29806

Placing null at the end of the List

I have a need to place null objects at the end of the List. Here is a sample what I have done for this purpose:

public static void main(String... args) {
    List<String> strings = Arrays.asList(new String[]{"A", null, "B"});

    for(String string : strings) {
        System.out.println(string);
    }

    System.out.println("==================");

    List<String> result = new ArrayList<String>();
    List<String> nullStrings = new ArrayList<String>();

    for(String string : strings) {
        if(string != null) {
            result.add(string);         
        } else {
            nullStrings.add(string);
        }
    }

    result.addAll(nullStrings);

    for(String string : result) {
        System.out.println(string);
    }
}

I am looking forward to a more efficient and intelligent way to do this. Is it possible to swap inside the actual list so that null node get placed at the end, so that I don't need the other two list(nullStrings, result) and extra iteration.

Update

Sorting will not work for my case. This sample code I made just for testing purpose. Actually I have a different type of Object. Also Sorting will break the position.

Say I have this null, Obj2, Obj1, if do anything like sorting it may happens Obj1, Obj2, null. But I need Obj2, Obj1, null.

Upvotes: 3

Views: 3165

Answers (5)

Manik Maurya
Manik Maurya

Reputation: 1

List<String> list = new ArrayList<>();
list.add("BR64");
list.add("SWG620");
list.add("");
list.add("sw0");
list.add("R124");
list.add("R219");
list.add("TaGh20");
list.add("SW6505");
list.add("");
list.add(null);
list.add("SW_6505");
list.add("swd_157");
list.add("localhost");
list.add("qaGh20_241");
list.add("gen");
list.add(null);
list.add("taGh20");
list.add("zen");
list.add("QWG");
list.add("SWG62_");
list.add("SWG620");


Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        if (o1 != null && o2 != null && o1.length() > 0 && o2.length() > 0) {
            return (Character.toLowerCase(o1.charAt(0)) == Character.toLowerCase(o2.charAt(0)))
                    ? o1.compareTo(o2)
                    : (Character.toLowerCase(o1.charAt(0)) + o1.substring(1))
                            .compareTo((Character.toLowerCase(o2.charAt(0)) + o2.substring(1)));
        } else {
            return (o1 == o2) ? 0 : ((o1 == null || o1 == "") ? 1 : -1);
        }
    }
});
System.out.println(list);

Output-: [BR64, gen, localhost, QWG, qaGh20_241, R124, R219, SW6505, SWG620, SWG620, SWG62_, SW_6505, sw0, swd_157, TaGh20, taGh20, zen, , , null, null]

Upvotes: 0

johnchen902
johnchen902

Reputation: 9599

Just move non-null elements to the front and fill the rest of the list with null.

int j = 0;
for (int i = 0; i < strings.size(); i++)
    if (strings.get(i) != null){
        strings.set(j, strings.get(i));
        j++;
    }
for (; j < strings.size(); j++)
    strings.set(j, null);

If you are using LinkedList (or something not a RandomAccess), you'll need ListIterator

ListIterator<String> j = strings.listIterator();
for (ListIterator<String> i = strings.listIterator(); i.hasNext();) {
    String s = i.next();
    if (s != null) {
        j.next();
        j.set(s);
    }
}
while (j.hasNext()) {
    j.next();
    j.set(null);
}

Upvotes: 4

Fedy2
Fedy2

Reputation: 3207

You can sort it using Collections.sort and a custom Comparator.

Here the compare code:

@Override 
public int compare(String left, String right) {
 if (left == right) {
   return 0;
 }
 if (left == null) {
   return 1;
 }
 if (right == null) {
   return -1;
 }
 return 0;
 }

Note that elements that have an equal value according to this Comparator won't be re-ordered. From Collections.sort:

This sort is guaranteed to be stable: equal elements will not be reordered as a result of the sort.

Upvotes: 11

JB Nizet
JB Nizet

Reputation: 691755

The general strategy looks fine to me. I would bring the following changes:

  • initialize the result list with the appropriate size
  • don't use a separate list for nulls. At the end of the iteration, you just need to compare the length of the initial list with the length of the result list to know how many nulls you need to add.

Although making a copy of the list will use more memory, it could well be faster than changing the initial list, because removing elements needs to move all the subsequent elements each time. And sorting is N*log(N), whereas copying elements is O(N).

[EDIT owlstead]

public static List<String> moveNullsToEnd(final List<String> strings) {

    final List<String> newStrings = new ArrayList<String>(strings.size());

    for (String string : strings) {
        if (string != null) {
            newStrings.add(string);
        }
    }

    for (int i = 0, remaining = strings.size() - newStrings.size(); i < remaining; i++) {
        newStrings.add(null);
    }

    return newStrings;
}

Upvotes: 2

Kalaiarasan Manimaran
Kalaiarasan Manimaran

Reputation: 1658

Below code you can use

Remove all the null elements

int noOfNull =0 ,i=0;

for(; i< strings.size() ; i++)
{
    if(strings.get(i) == null)
    {
        noOfNull++;
    }
}
strings.removeAll(Collections.singleton(null));

Filling the array with null after the not null elements

for(i =strings.size(); i < strings.size()+noOfNull ; i++)
        {
            strings.add(null);
        }

Upvotes: 1

Related Questions