Rearrangement of objects in arraylist

public void go()
{
    ArrayList<String> fruits = new ArrayList<>();

    fruits.add("pear");
    fruits.add("pineapple");
    fruits.add("oranges");
    fruits.add("banana");
    fruits.add("apple");

    for(String str: fruits)
    {
         if(str.contains("apple"))
         {   /* I would like anything containing 'apple' 
          * i.e. apple & pineapple to be placed on top of the array*/   }
    }
    for(String str: fruits)
    {
        System.out.println(str);
    }
}

As you can see, the above code if printed as normal, would result in

pear, pineapple, oranges, banana, apple.

How can I sort this array, in the way that anything with apple would be sorted alphabetically first, and those that are not should remain the same. i.e, the output should looks like:

apple, pineapple, pear, oranges, banana.

Is there even a possible way to go around it??

Jon Skeet
people
quotationmark

I would split the list into two: items that contain apple, and items that don't. Then sort the apple-containing list, and then append the non-apple-containing list.

List<String> apples = new ArrayList<>();
List<String> nonApples = new ArrayList<>();
for (String fruit : fruits) {
  if (fruit.contains("apple")) {
    apples.add(fruit);
  } else {
    nonApples.add(fruit);
  }
}
Collections.sort(apples);
apples.addAll(nonApples);
// apples now contains what you want. Of course, it's now misnamed :)

As an alternative for the last few lines, creating a copy of the apples-only list:

List<String> result = new ArrayList<>(apples);
Collections.sort(result);
result.addAll(nonApples);

This is all pretty much equivalent to JB Nizet's approach, except it only checks for apple-containment once per item, instead of going through the original list twice. Unless your real check is really expensive, it's unlikely that this will be a performance bottleneck, so use whichever approach you prefer.

It's not clear whether you need the results to be in your original list, or whether it's fine to have a new list with the result.

If you need to put them in your original list, you can always use:

for (int i = 0; i < result.size(); i++) {
  fruits.set(i, result.get(i));
}

The approaches using Collections.sort which rely on it being stable are interesting - but I personally feel they're less clear than this approach.

people

See more on this question at Stackoverflow