Sorted by name java

How to sort the name along with age in java

Currently you are a) only comparing by one attribute and b) not really making use of Java 8’s new features.

With Java 8 you can use method references and chained comparators, like this:

Collections.sort(persons, Comparator.comparing(Person::getFname) .thenComparingInt(Person::getAge)); 

This will compare two Person instances first by their fname and — if that is equal — by their age (with a slight optimization to thenComparingInt to avoid boxing).

You need to compare for names first. If the names are the same, then and only then the result depends on comparing the age

public static void main(String[] args) < Listpersons = new ArrayList<>(); persons.add(new Person("tarun", 28)); persons.add(new Person("arun", 29)); persons.add(new Person("varun", 12)); persons.add(new Person("arun", 22)); Collections.sort(persons, new Comparator() < public int compare(Person t, Person t1) < int comp = t.getFname().compareTo(t1.getFname()); if (comp != 0) < // names are different return comp; >return t.getAge() - t1.getAge(); > >); System.out.println(persons); >> 

if you want to change from ascending to descending, just change the sign. e.g.

 int comp = t1.getFname().compareTo(t.getFname()); 

You are on the right path, but your compare method is incomplete.

Since compare is called to decide which item in each pair is to go before the other, it must include all comparison logic, not only the tie-breaking one. Your code sorts on the age alone, ignoring the name completely.

The logic should go like this:

  • Compare names using t.getFname().compareTo(t1.getFname())
  • If names are not the same, return the result of comparison
  • Otherwise, return the result of comparing ages.

Proper way of comparing integers is with the static Integer.compare method, i.e. Integer.compare(t.getAge(), t1.getAge()) .

Your Comparator is only sorting by age, not by name.

You could try it like that:

new Comparator() < @Override public int compare(Person t, Person t1) < int ret = t.getFname().compareTo(t1.getFname()); if (ret == 0) < ret = Integer.compare(t.getAge(), t1.getAge()); >return ret; > > 

You could also think about implementing Comparable in the Person class itself:

class Person implements Comparable  < @Override public int compareTo(Person p) < int ret = fname.compareTo(p.fname); if (ret == 0) < ret = Integer.compare(age, p.getAge()); >return ret; > > 

You can use Comparator.comparing method, introduced in Java 8, returns a Comparator object that will use the specified field as the sort key.

final Function byAge = person -> person.getAge(); final Function byTheirName = person -> person.getFname(); System.out.println("Sorted in ascending order by age and name: "); List sortedlist = people.stream() .sorted(Comparator.comparing(byAge).thenComparing(byTheirName)) .collect(Collectors.toList()); sortedlist.forEach(System.out::println); 

We first created two lambda expressions, one to return the age of a given person and the other to return that person’s name. We then combined these two lambda expressions in the call to the sorted() method to compare on both properties. The comparing() method created and returned a Comparator to compare based on age. On the returned Comparator we invoked the thenComparing() method to create a composite comparator that compares based on both age and name

Читайте также:  Java руководство для программиста

Источник

How to sort by two fields in Java?

I have array of objects person (int age; String name;) . How can I sort this array alphabetically by name and then by age? Which algorithm would you use for this ?

15 Answers 15

You can use Collections.sort as follows:

private static void order(List persons) < Collections.sort(persons, new Comparator() < public int compare(Object o1, Object o2) < String x1 = ((Person) o1).getName(); String x2 = ((Person) o2).getName(); int sComp = x1.compareTo(x2); if (sComp != 0) < return sComp; >Integer x1 = ((Person) o1).getAge(); Integer x2 = ((Person) o2).getAge(); return x1.compareTo(x2); >>); > 

List is now sorted by name, then by age.

String.compareTo «Compares two strings lexicographically» — from the docs.

Collections.sort is a static method in the native Collections library. It does the actual sorting, you just need to provide a Comparator which defines how two elements in your list should be compared: this is achieved by providing your own implementation of the compare method.

Since the OP already has their own object class, it would make more sense to implement Comparable . See the answer by @berry120

Mini code review: the else clause is redundant because the first return acts as a guard clause. Great answer though, worked a treat for me.

As this question/ answer still gets linked, please note that with Java SE 8 this became much simpler. If there are getters you can write Comparator comparator = Comparator.comparing(Person::getName).thenComparingInt(Person::getAge);

For those able to use the Java 8 streaming API, there is a neater approach that is well documented here: Lambdas and sorting

I was looking for the equivalent of the C# LINQ:

I found the mechanism in Java 8 on the Comparator:

So here is the snippet that demonstrates the algorithm.

 Comparator comparator = Comparator.comparing(person -> person.name); comparator = comparator.thenComparing(Comparator.comparing(person -> person.age)); 

Check out the link above for a neater way and an explanation about how Java’s type inference makes it a bit more clunky to define compared to LINQ.

Читайте также:  What is html viewer on android

Here is the full unit test for reference:

@Test public void testChainedSorting() < // Create the collection of people: ArrayListpeople = new ArrayList<>(); people.add(new Person("Dan", 4)); people.add(new Person("Andi", 2)); people.add(new Person("Bob", 42)); people.add(new Person("Debby", 3)); people.add(new Person("Bob", 72)); people.add(new Person("Barry", 20)); people.add(new Person("Cathy", 40)); people.add(new Person("Bob", 40)); people.add(new Person("Barry", 50)); // Define chained comparators: // Great article explaining this and how to make it even neater: // http://blog.jooq.org/2014/01/31/java-8-friday-goodies-lambdas-and-sorting/ Comparator comparator = Comparator.comparing(person -> person.name); comparator = comparator.thenComparing(Comparator.comparing(person -> person.age)); // Sort the stream: Stream personStream = people.stream().sorted(comparator); // Make sure that the output is as expected: List sortedPeople = personStream.collect(Collectors.toList()); Assert.assertEquals("Andi", sortedPeople.get(0).name); Assert.assertEquals(2, sortedPeople.get(0).age); Assert.assertEquals("Barry", sortedPeople.get(1).name); Assert.assertEquals(20, sortedPeople.get(1).age); Assert.assertEquals("Barry", sortedPeople.get(2).name); Assert.assertEquals(50, sortedPeople.get(2).age); Assert.assertEquals("Bob", sortedPeople.get(3).name); Assert.assertEquals(40, sortedPeople.get(3).age); Assert.assertEquals("Bob", sortedPeople.get(4).name); Assert.assertEquals(42, sortedPeople.get(4).age); Assert.assertEquals("Bob", sortedPeople.get(5).name); Assert.assertEquals(72, sortedPeople.get(5).age); Assert.assertEquals("Cathy", sortedPeople.get(6).name); Assert.assertEquals(40, sortedPeople.get(6).age); Assert.assertEquals("Dan", sortedPeople.get(7).name); Assert.assertEquals(4, sortedPeople.get(7).age); Assert.assertEquals("Debby", sortedPeople.get(8).name); Assert.assertEquals(3, sortedPeople.get(8).age); // Andi : 2 // Barry : 20 // Barry : 50 // Bob : 40 // Bob : 42 // Bob : 72 // Cathy : 40 // Dan : 4 // Debby : 3 > /** * A person in our system. */ public static class Person < /** * Creates a new person. * @param name The name of the person. * @param age The age of the person. */ public Person(String name, int age) < this.age = age; this.name = name; >/** * The name of the person. */ public String name; /** * The age of the person. */ public int age; @Override public String toString() < if (name == null) return super.toString(); else return String.format("%s : %d", this.name, this.age); >> 

Источник

How to sort a List alphabetically using Object name field

object1 and object2 need to be of type Campaign , and the compare function is object1.getName().compareTo(object2.getName()) .

You mix List and Comparator . You can’t do that. Either you have List and Comparator or List and Comparator

18 Answers 18

From your code, it looks like your Comparator is already parameterized with Campaign . This will only work with List . Also, the method you’re looking for is compareTo .

Or if you are using Java 1.8

list .stream() .sorted((object1, object2) -> object1.getName().compareTo(object2.getName())); 

One final comment — there’s no point in checking the list size. Sort will work on an empty list.

I think this is the best answer that distills everything into what the OP is looking for. And from the comments, I think he wants case-insensitive, so just switch the compareTo to compareToIgnoreCase

Читайте также:  Create constants in java

Minor improve in the first solution: we can do if (list.size() > 1) — as for 1 item no need to sort..

Try using sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList()); to get a new sorted list

list.sort(Comparator.comparing(Campaign::getName)); 

The most correct way to sort alphabetically strings is to use Collator , because of internationalization. Some languages have different order due to few extra characters etc.

 Collator collator = Collator.getInstance(Locale.US); if (!list.isEmpty()) < Collections.sort(list, new Comparator() < @Override public int compare(Campaign c1, Campaign c2) < //You should ensure that list doesn't contain null values! return collator.compare(c1.getName(), c2.getName()); >>); > 

If you don’t care about internationalization use string.compare(otherString) .

Have a look at Collections.sort() and the Comparator interface.

String comparison can be done with object1.getName().compareTo(object2.getName()) or object2.getName().compareTo(object1.getName()) (depending on the sort direction you desire).

If you want the sort to be case agnostic, do object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase()) .

and how do you suggest extracting that field called nama from the Object type? this answer is not complete.

Name extraction depends on the type of the object. I supposed it is just a placeholder type. If you cannot give a more concrete type, you might end using reflection.

public class ObjectComparator implements Comparator  < public int compare(Object obj1, Object obj2) < return obj1.getName().compareTo(obj2.getName()); >> 

Please replace Object with your class which contains name field

ObjectComparator comparator = new ObjectComparator(); Collections.sort(list, comparator); 

if you want o make reverse sorting, just replace obj1.getName().compareTo(obj2.getName() with obj2.getName().compareTo(obj1.getName() in the comparator class

Here is a version of Robert B’s answer that works for List and sorting by a specified String property of the object using Reflection and no 3rd party libraries

/** * Sorts a List by the specified String property name of the object. * * @param list * @param propertyName */ public static void sortList(List list, final String propertyName) < if (list.size() >0) < Collections.sort(list, new Comparator() < @Override public int compare(final T object1, final T object2) < String property1 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object1); String property2 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object2); return property1.compareToIgnoreCase (property2); >>); > > public static Object getSpecifiedFieldValue (String property, Object obj) < Object result = null; try < ClassobjectClass = obj.getClass(); Field objectField = getDeclaredField(property, objectClass); if (objectField!=null) < objectField.setAccessible(true); result = objectField.get(obj); >> catch (Exception e) < >return result; > public static Field getDeclaredField(String fieldName, Class type) < Field result = null; try < result = type.getDeclaredField(fieldName); >catch (Exception e) < >if (result == null) < Classsuperclass = type.getSuperclass(); if (superclass != null && !superclass.getName().equals("java.lang.Object")) < return getDeclaredField(fieldName, type.getSuperclass()); >> return result; > 

Источник

Оцените статью