54

My array does not contain any string. But its contains object references. Every object reference returns name, id, author and publisher by toString method.

public String toString() {
        return (name + "\n" + id + "\n" + author + "\n" + publisher + "\n");
}

Now I need to sort that array of objects by the name. I know how to sort, but I do not know how to extract the name from the objects and sort them.

2
  • 3
    Implement a Comparator and use it for sorting. Commented Sep 19, 2013 at 13:37
  • 1
    In the Comparator split the string and use the first element as the name. Commented Sep 19, 2013 at 13:41

13 Answers 13

62

You can try something like this:

List<Book> books = new ArrayList<Book>();

Collections.sort(books, new Comparator<Book>(){

  public int compare(Book o1, Book o2)
  {
     return o1.name.compareTo(o2.name);
  }
});
Sign up to request clarification or add additional context in comments.

Comments

51

You have two ways to do that, both use the Arrays utility class

  1. Implement a Comparator and pass your array along with the comparator to the sort method which take it as second parameter.
  2. Implement the Comparable interface in the class your objects are from and pass your array to the sort method which takes only one parameter.

Example

class Book implements Comparable<Book> {
    public String name, id, author, publisher;
    public Book(String name, String id, String author, String publisher) {
        this.name = name;
        this.id = id;
        this.author = author;
        this.publisher = publisher;
    }
    public String toString() {
        return ("(" + name + ", " + id + ", " + author + ", " + publisher + ")");
    }
    @Override
    public int compareTo(Book o) {
        // usually toString should not be used,
        // instead one of the attributes or more in a comparator chain
        return toString().compareTo(o.toString());
    }
}

@Test
public void sortBooks() {
    Book[] books = {
            new Book("foo", "1", "author1", "pub1"),
            new Book("bar", "2", "author2", "pub2")
    };

    // 1. sort using Comparable
    Arrays.sort(books);
    System.out.println(Arrays.asList(books));

    // 2. sort using comparator: sort by id
    Arrays.sort(books, new Comparator<Book>() {
        @Override
        public int compare(Book o1, Book o2) {
            return o1.id.compareTo(o2.id);
        }
    });
    System.out.println(Arrays.asList(books));
}

Output

[(bar, 2, author2, pub2), (foo, 1, author1, pub1)]
[(foo, 1, author1, pub1), (bar, 2, author2, pub2)]

Comments

46

Java 8


Using lambda expressions

Arrays.sort(myTypes, (a,b) -> a.name.compareTo(b.name));

Test.java

public class Test {

    public static void main(String[] args) {

        MyType[] myTypes = {
                new MyType("John", 2, "author1", "publisher1"),
                new MyType("Marry", 298, "author2", "publisher2"),
                new MyType("David", 3, "author3", "publisher3"),
        };

        System.out.println("--- before");
        System.out.println(Arrays.asList(myTypes));
        Arrays.sort(myTypes, (a, b) -> a.name.compareTo(b.name));
        System.out.println("--- after");
        System.out.println(Arrays.asList(myTypes));

    }

}

MyType.java

public class MyType {

    public String name;
    public int id;
    public String author;
    public String publisher;

    public MyType(String name, int id, String author, String publisher) {
        this.name = name;
        this.id = id;
        this.author = author;
        this.publisher = publisher;
    }

    @Override
    public String toString() {
        return "MyType{" +
                "name=" + name + '\'' +
                ", id=" + id +
                ", author='" + author + '\'' +
                ", publisher='" + publisher + '\'' +
                '}' + System.getProperty("line.separator");
    }
}

Output:

--- before
[MyType{name=John', id=2, author='author1', publisher='publisher1'}
, MyType{name=Marry', id=298, author='author2', publisher='publisher2'}
, MyType{name=David', id=3, author='author3', publisher='publisher3'}
]
--- after
[MyType{name=David', id=3, author='author3', publisher='publisher3'}
, MyType{name=John', id=2, author='author1', publisher='publisher1'}
, MyType{name=Marry', id=298, author='author2', publisher='publisher2'}
]

Using method references

Arrays.sort(myTypes, MyType::compareThem);

where compareThem has to be added in MyType.java:

public static int compareThem(MyType a, MyType b) {
    return a.name.compareTo(b.name);
}

4 Comments

If you want to use lambda expressions in Android Studio, you should look at this page: developer.android.com/studio/write/java8-support.html
In the above case, instead of name , if it was id, how can we do?
I try with replacing name with id, but the error was "dereferencing not possible for int,) so i converted the int to string. Now there is no error, but it is not sorting?
16

Update for Java 8 constructs

Assuming a Book class with a name field getter, you can use Arrays.sort method by passing an additional Comparator specified using Java 8 constructs - Comparator default method & method references.

Arrays.sort(bookArray, Comparator.comparing(Book::getName));

Also, it's possible to compare on multiple fields using thenComparing methods.

Arrays.sort(bookArray, Comparator.comparing(Book::getName)
      .thenComparing(Book::getAuthor))
      .thenComparingInt(Book::getId));

Comments

4

With Java 8, you can use a reference method.

You could add compare method to your Book class

class Book {
    public static int compare(Book a, Book b) {
        return a.name.compareTo(b.name);
    }
}

And then you could do this :

Arrays.sort(books, Book::compare);

Here is the full example:

class Book {
    String name;
    String author;

    public Book(String name, String author) {
        this.name = name;
        this.author = author;
    }

    public static int compareBooks(Book a, Book b) {
        return a.name.compareTo(b.name);
    }

    @Override
    public String toString() {
        return "name : " + name + "\t" + "author : " + author;
    }

    public static void main(String[] args) {
        Book[] books = {
                new Book("Book 3", "Author 1"),
                new Book("Book 2", "Author 2"),
                new Book("Book 1", "Author 3"),
                new Book("Book 4", "Author 4")
        };
        Arrays.sort(books, Book::compareBooks);
        Arrays.asList(books).forEach(System.out::println);
    }
}

1 Comment

3
[Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
 Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
 Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]
public void whenComparing_thenSortedByName() {
    Comparator<Employee> employeeNameComparator
            = Comparator.comparing(Employee::getName);
    Arrays.sort(employees, employeeNameComparator);
    assertTrue(Arrays.equals(employees, sortedEmployeesByName));
}

result

[Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
 Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
 Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]

Comments

3
 Arrays.sort(yourList,new Comparator<YourObject>() {

    @Override
    public int compare(YourObject o1, YourObject o2) {
        return compare(o1.getYourColumn(), o2.getYourColumn());
    }
});

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Read this.
0

Sometimes you want to sort an array of objects on an arbitrary value. Since compareTo() always uses the same information about the instance, you might want to use a different technique. One way is to use a standard sorting algorithm. Let's say you have an array of books and you want to sort them on their height, which is stored as an int and accessible through the method getHeight(). Here's how you could sort the books in your array. (If you don't want to change the original array, simply make a copy and sort that.)

`int tallest; // the index of tallest book found thus far
 Book temp; // used in the swap
 for(int a = 0; a < booksArray.length - 1; a++) {
   tallest = a; // reset tallest to current index
   // start inner loop at next index
   for(int b = a + 1; b < booksArray.length; b++)
     // check if the book at this index is taller than the
     // tallest found thus far
     if(booksArray[b].getHeight() > booksArray[tallest].getHeight())
       tallest = b;
   // once inner loop is complete, swap the tallest book found with
   // the one at the current index of the outer loop
   temp = booksArray[a];
   booksArray[a] = booksArray[tallest];
   booksArray[tallest] = temp;
 }`

When this code is done, the array of Book object will be sorted by height in descending order--an interior designer's dream!

Comments

0

You can implement the "Comparable" interface on a class whose objects you want to compare.

And also implement the "compareTo" method in that.

Add the instances of the class in an ArrayList

Then the "java.utils.Collections.sort()" method will do the necessary magic.

Here's--->(https://deva-codes.herokuapp.com/CompareOnTwoKeys) a working example where objects are sorted based on two keys first by the id and then by name.

Comments

0

Let's take an example of Book class and build a list of book objects:-

public class Book {
  String name;
  String author;
  double rating;
}

Book book1 = new Book("book1", "author1", 3.0);
Book book2 = new Book("book2", "author2", 5);
Book book3 = new Book("book3", "author1", 4.0);
Book book4 = new Book("book4", "author2", 2.5);
Book book5 = new Book("book5", "author1", 4.0);

List<Book> library = Arrays.asList(book1, book2, book3, book4, book5);

We can sort a list of objects using Comparator.comparing(). We can also chain it with .thenComparing() to sort by multiple fields. Let's look at examples:-

// Sort in ascending order
Collections.sort(library, Comparator.comparing(Book::getAuthor));
Collections.sort(library, Comparator.comparingDouble(Book::getRating));

// Sort in descending order
Collections.sort(library, Comparator.comparing(Book::getAuthor).reversed());
Collections.sort(library, Comparator.comparingDouble(Book::getRating).reversed());

// Sort by multiple fields in ascending order
Collections.sort(library, Comparator.comparing(Book::getAuthor)
            .thenComparingDouble(Book::getRating)
            .thenComparing(Book::getName));

// Sort by multiple fields in ascending then descending order
Collections.sort(library, Comparator.comparing(Book::getAuthor)
        .thenComparing((b1, b2) -> Double.compare(b2.getRating(), b1.getRating()))
        .thenComparing((b1, b2) -> b2.getName().compareTo(b1.getName())));

Source: CodingNConcepts

Comments

0

tl;dr

To sort by output of toString:

Arrays.sort( persons , Comparator.comparing( Person :: toString ) );

Sort by toString

Other Answers assume you have access to the class and its fields. If so, use those other approaches. But I will take your Question at face value: How to sort by toString.

To answer your Question directly, how to sort by toString output, use Arrays.sort with a Comparator based on a method reference of toString.

Arrays.sort( persons , Comparator.comparing( Person :: toString ) );

As an example, let's define a record class Person. You can define a record locally, if you want, or as a nested or separate class.

record Person( String firstName , String lastName ) { }

With a record, the toString method override is implicitly implemented to access each and every field in the order of their definition. So in our case, toString produces text consisting of the first name followed by the last name.

Sorting is made easier in Java 8+ by way of Comparator.comparing.

Let's generate some example data to exercise this code.

Person[] persons =
        List.of(
                        new Person( "Bob" , "Yates" ) ,
                        new Person( "Carol" , "Zamora" ) ,
                        new Person( "Alice" , "Anderson" ) ,
                        new Person( "Davis" , "Xavier" ) ,
                        new Person( "Alice" , "Abercrombie" )
                )
                .toArray( Person[] :: new );

Dump the array to console after sorting. Before Java 25, swap out IO for System.out.

Arrays.stream( persons ).forEach( IO :: println );

When run:

Person[firstName=Alice, lastName=Abercrombie]
Person[firstName=Alice, lastName=Anderson]
Person[firstName=Bob, lastName=Yates]
Person[firstName=Carol, lastName=Zamora]
Person[firstName=Davis, lastName=Xavier]

Notice how all the elements are in order by first name. In the case of a collision between first names, such as Alice here, the last name acts as the tie-breaker given that it is the last part of the String object being compared. Here we see Alice Abercrombie comes before Alice Anderson.

Comments

-1
public class Student implements Comparable<Student> {

    private int sid;
    private String sname;

    public Student(int sid, String sname) {
        super();
        this.sid = sid;
        this.sname = sname;
    }

    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    @Override
    public String toString() {
        return "Student [sid=" + sid + ", sname=" + sname + "]";
    }

    public int compareTo(Student o) {
        if (this.getSname().compareTo(o.getSname()) > 1) {
            return toString().compareTo(o.getSname());
        } else if (this.getSname().compareTo(o.getSname()) < 1) {
            return toString().compareTo(o.getSname());
        }
        return 0;
    }

}

1 Comment

adding sort check in Test class in below application
-2
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        List<Student> str = new ArrayList<Student>();
        str.add(new Student(101, "aaa"));
        str.add(new Student(104, "bbb"));
        str.add(new Student(103, "ccc"));
        str.add(new Student(105, "ddd"));
        str.add(new Student(104, "eee"));
        str.add(new Student(102, "fff"));

        Collections.sort(str);
        for (Student student : str) {
            System.out.println(student);
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.