sTg
sTg

Reputation: 4424

Java: Sort a list of Objects using Comparator with second word of the property

I have a list of objects which i want to sort on basis of name. I have done coding where it does get sorted on basis of name but i have a slight different requirement.

The names are for Example which i have currently sorted using the below code:

Bull AMP
Cat DEF
Dog AMP
Frog STR
Zebra DEF

But i want the name sorted on the basis of second word in the name. Basically the list should be something like this:

Bull AMP
Dog AMP
Cat DEF
Zebra DEF
Frog STR

Below is my code:

Object Class:

public class AnimalData implements Serializable
{
    private static final long serialVersionUID = 3952396152688462601L;
    public String name;
    public long age;
    private String animal;
    private String animalParts;
    private String animalType;
}

Comparator Class

public class AnimalDataComparer implements Comparator<AnimalData> 
      {
  @Override
  public int compare(final AnimalData object1, final AnimalData object2) 
  {
          return object1.getName().compareTo(object2.getName());
  }
  }

Sorting using Collections

  private List<AnimalData> AnimalDataList;

  Collections.sort(AnimalDataList, AnimalDataComparer);

Upvotes: 3

Views: 2585

Answers (4)

nineunderground
nineunderground

Reputation: 90

In Java 8 Streams mode:

Comparator<? super Animal> animalComparator = (a, b) -> {
        StringTokenizer firstTokenizer = new StringTokenizer(a.getName(), " ");
        firstTokenizer.nextToken();
        StringTokenizer secondTokenizer = new StringTokenizer(b.getName(), " ");
        secondTokenizer.nextToken();
        return firstTokenizer.nextToken().compareTo(secondTokenizer.nextToken());
    };

    myList = myList.stream().sorted(animalComparator).collect(Collectors.toList());

Upvotes: 1

Arnav Borborah
Arnav Borborah

Reputation: 11759

You need to implement this yourself, as follows, assuming that the word is part of name, with substring() and indexOf():

@Override
public int compare(final AnimalData object1, final AnimalData object2) 
{
    return object1.getName().substring(
        object1.getName().indexOf(" ") 
    ).compareTo(object2.getName().substring(
        object2.getName().indexOf(" ")
    ));
}

If for some reason you have more than two words and the last is the one you want, then use lastIndexOf()

Upvotes: 3

Abhishek Honey
Abhishek Honey

Reputation: 645

Here it is

OUTPUT::

[AnimalData [name=Dog AMP], AnimalData [name=Cat DEF], AnimalData [name=Zebra DEF], AnimalData [name=Frog STR]]

import java.io.IOException;
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class test {
    public static void main(String[] args) throws IOException, ParseException {

        AnimalData data1 = new AnimalData("Cat DEF");
        AnimalData data2 = new AnimalData("Dog AMP");
        AnimalData data3 = new AnimalData("Frog STR");
        AnimalData data4 = new AnimalData("Zebra DEF");
        List<AnimalData> list = new ArrayList<>();
        list.add(data1);
        list.add(data2);
        list.add(data3);
        list.add(data4);
        Collections.sort(list);
        System.out.println(list);

    }
}

class AnimalData implements Serializable, Comparable<AnimalData> {
    private static final long serialVersionUID = 3952396152688462601L;
    public String name;
    public long age;
    private String animal;
    private String animalParts;
    private String animalType;

    public AnimalData(String name) {
        super();
        this.name = name;
    }

    @Override
    public int compareTo(AnimalData o) {
        String secondPartThis = this.name.split(" ")[1];
        String secondPartObject = o.name.split(" ")[1];
        return secondPartThis.compareTo(secondPartObject);
    }

    @Override
    public String toString() {
        return "AnimalData [name=" + name + "]";
    }

Upvotes: 0

Malte Hartwig
Malte Hartwig

Reputation: 4555

Change your Comparator like this:

public class AnimalDataComparer implements Comparator<AnimalData> 
{
    @Override
    public int compare(final AnimalData object1, final AnimalData object2) 
    {
      return object1.getName().split(" ")[1].compareTo(object2.getName().split(" ")[1]);
    }
}

or use Java's newer Comparator API:

Comparator<AnimalData> c = Comparator.comparing(animal -> animal.getName().split(" ")[1]);

Note that this is assuming that all names actually have two words. If you do not know that for sure, you need to check before accessing the split array.

Aside from all that, you might want to think about the other comments and split the name in your constructor and have two fields, name and category. Or you could write a getter for category, in which you do the splitting and validation.

Upvotes: 4

Related Questions