String alphabetical order using List or Arraylist [duplicate] - java

This question already has answers here:
How to sort List of objects by some property
(17 answers)
Closed 3 years ago.
In this program I sorted strings in Alphabetic way in Simple Array but how can I do the same thing using List or ArrayList, Suppose I have a class Students and I want to order names in an alphabetically way, so how can I do that?
public class CityData{
public static String citynames[]= {"Hyderabad","Karachi","Abtabad","AzadKashmir"};
public static void main(String args[]) {
int size=citynames.length;
String temp=null;
for(int i=0; i<size; i++) {
for(int j=i+1; j<size; j++) {
if(citynames[i].compareTo(citynames[j])>0) {
temp=citynames[i];
citynames[i]=citynames[j];
citynames[j]=temp; }
}
System.out.println(citynames[i]);
}
}
}
Result:
Abtabad
AzadKashmir
Hyderabad
Karachi

You can sort the collections based on your requirements.
If the input objects for collections is implementing the Comparable interface like String, Integer, Double classes, then you can directly use Collections.sort() method from Collections util class
List<String> al = new ArrayList<>();
al.add("Hyderabad");
al.add("Karachi");
al.add("Abtabad");
al.add("AzadKashmir");
al.add("Udupi");
al.add("Jammu");
Collections.sort(al);
Or you can sort the list based on your requirement.(Reverse alphabetical Order)
Collections.sort(al, (str1, str2) -> str2.compareTo(str1));
If you don't want to use the Collections class, then directly use the sort() method present in List interface.
i. Albhabetical Order
al.sort((str1, str2) -> str1.compareTo(str1));
ii. Reverse Albhabetical Order
al.sort((str1, str2) -> str2.compareTo(str1));
The above solution is for the Objects where the class implements the Comparable Interface like String, Integer, Double, etc...
When to sort the Custom Classes, you need to implement sort by Comparator class or Lambda expression for the Comparator.
Consider you have a Student Class, and need to sort by city names. You can use below code.
Student Class
public class Student {
private String name;
private String city;
public Student() {}
public Student(String name, String city) {
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
#Override
public String toString() {
return "Student -> [name=" + name + ", city=" + city + "]";
}
}
Sorting By Collection Class sort() method
Student st1 = new Student("Samir", "Hyderabad");
Student st2 = new Student("Akbar", "Karachi");
Student st3 = new Student("Ramu", "Abtabad");
Student st4 = new Student("Rahim", "AzadKashmir");
Student st5 = new Student("Sardar", "Udupi");
Student st6 = new Student("Fahad khan", "Jammu");
List<Student> al2 = new ArrayList<>();
al2.add(st1);
al2.add(st2);
al2.add(st3);
al2.add(st4);
al2.add(st5);
al2.add(st6);
//Alphabetical Order
Collections.sort(al2, (std1, std2) -> std1.getCity().compareTo(std2.getCity()));
//Reverse Alphabetical Order
Collections.sort(al2, (std1, std2) -> std2.getCity().compareTo(std1.getCity()));
By using List.sort() method
//Alphabetical Order
al2.sort((std1, std2) -> std1.getCity().compareTo(std2.getCity()));
//Reverse Alphabetical Order
al2.sort((std1, std2) -> std1.getCity().compareTo(std2.getCity()));

What you are looking for is actually pretty simple to do:
Instead of using citynames[i] or citynames[j], for Lists and ArrayLists, you use citynames.get(i) or citynames.get(j).
Just think of List.get() is the same as the brackets you put before for the simple arrays.
Just remember, when you want to set a value, you actually have to use the List.set(int index, Object value).
The same can be said if you are trying to get the length of the List or ArrayList. You can simply replace citynames.length to citynames.size();
public static void main(String args[]) {
int size=citynames.size();
String temp=null;
for(int i=0; i<size; i++) {
for(int j=i+1; j<size; j++) {
if(citynames.get(i).compareTo(citynames.get(j))>0) {
temp=citynames.get(i);
citynames.set(i, citynames.get(j));
citynames.set(j, temp); }
}
System.out.println(citynames.get(i));
}
}
Update: Better Solution:
Note: When using Collections.sort() it is important to make sure the object type of the array implements Comparable. the Collections.sort() uses the compareTo() within the object class to sort the elements.
public class Main(){
import java.util.Collections;
public static void main(String args[]) {
ArrayList<City> citynames = new ArrayList<City>();
citynames.add("Hyderabad");
citynames.add("Karachi");
citynames.add("Abtabad");
citynames.add("AzadKashmir");
Collections.sort(citynames);
for(cityname : citynames)
System.out.println(cityname);
}
}
public class City implements Comparable{
private String name;
// Constructor
public City(String name){
this.name = name;
}
// Getter method
public String getName(){
return name;
}
// compareTo Method
public int compareTo(City other){
return name.compareTo(other.getName());
}
// Other methods may exist
}
For more information: https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html

I do not have the rights to comment yet, hence adding at as an answer.
You can google this easily and also lookup API for sorting collections.
Code in java 8
public class ArrayListSort {
public static String citynames[] = { "Hyderabad", "Karachi", "Abtabad", "AzadKashmir" };
public static void main(String args[]) {
Student stud1 = new Student("Alex", 20);
Student stud2 = new Student("Bryan", 21);
Student stud3 = new Student("Chris", 22);
Student stud4 = new Student("Dan", 23);
List<Student> students = new ArrayList<>(Arrays.asList(stud4, stud3, stud2, stud1));
Collections.sort(students);
for(Student stud: students){
System.out.println(stud.getName());
}
}
}
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return age;
}
#Override
public int compareTo(Student other) {
return this.name.compareTo(other.name);
}
}
Edit 1 to answer your comment, look up Comparable interface

Related

How to check if a string already exist in ArrayList?

I made this Student ArrayList that have name, age and number variable. I manually input 3 student. I want to check if a name already exist in my list. I tried to use list.contains but it seems not working. Are there certain way to do for this kind of ArrayList?
public class CompareToeX {
public static void main(String[] args) {
ArrayList<Student> obj=new ArrayList<Student>();
obj.add(new Student("Peter", 27,1));
obj.add(new Student("John",26,7));
obj.add(new Student("Jack",21,5));
if(obj.contains("Peter")){
System.out.println("Peter on is on the list!");
} else {
System.out.println("Peter is not on the list!");
}
}
}
This is the Student class
public class Student{
private String studentName;
private int age;
private int rollno;
public Student(String studentName, int age, int rollno){
this.studentName=studentName;
this.age=age;
this.rollno=rollno;
}
public String getStudent(){
return studentName;
}
public int getAge(){
return age;
}
public int getRollno(){
return rollno;
}
public void setStudent(String Student){
studentName=Student;
}
public void setAge(int age){
this.age=age;
}
public void setRollno(int rollno){
this.rollno=rollno;
}
}
After I run, the result should show that peter is on the list right. But it goes the other way around. It seems that the contains method is not working.
A student isn't a name.
.contains() will fail here because the string "Peter" is not in the list. It obviously isn't; how could it be? This list only contains Student objects, not Strings, after all.
You'll have to write a for loop, or use streams.
boolean peterIsInTheList = false;
for (var s : students) {
if (s.getName().equals("peter")) peterIsInTheList = true;
}
or
boolean peterIsInTheList = students.stream()
.anyMatch(s -> s.getName().equals("peter"));
Alternatively you could use the idea of a map; change your data structure. Instead of using a list, have a map that maps first names onto student objects:
Map<String, Student> students = new HashMap<>();
students.put("peter", new Student(....));
if (students.containsKey("peter")) {
// peter is in the list
}
You are checking if the String Peter is in the list, or the list only contains Student object. So you can only check if Student is contained inside the list (be sure to implement the right equals/hashcode method if you wish to use .contains).
This will do
obj.stream()
.filter(student -> student.getStudent().contains("Peter"))
.findFirst()
.ifPresentOrElse(student -> System.out.println("Peter on is on the list!"), () -> System.out.println("Peter is not on the list!"));
Being not a default data type, I think you need to override some functions of ArrayList first, like the .compare() one.
It was answered here too
Java: to use contains in a ArrayList full of custom object should I override equals or implement Comparable/Comparator?

LinkedList with years

I have to code LinkedList with two positions. First is the name and the second is the year.
class Person
{
String name;
int year;
public Person(String name, int year) {
this.name = name;
this.year = year;
}
}
class LinkedListStart {
public static void main (String[] args) throws java.lang.Exception
{
LinkedList<Person> persons = new LinkedList<Person>();
persons.add(new Person("Joe", 2010));
persons.add(new Person("Jane", 2012));
persons.add(new Person("Charly", 1910));
persons.add(new Person("Daisy", 1908));
System.out.println("LinkedList : " + persons);
}
}
There are errors when I am running the code:
LinkedList : [Person#6d06d69c, Person#7852e922, Person#4e25154f, Person#70dea4e]
Is it possible to do it? I want do use for-each loop to find person who is below 1950.
How to code something like this?
You should define a class Person as follows:
class Person{
String name;
int year;
public Person(String name, int year) {
this.name = name;
this.year = year;
}
}
And then create a LinkedList as follows:
LinkedList<Person> persons = new LinkedList<>();
You could combine them both into one String like names.add("Joe 2010") (NOT a recommended, or particularly good approach) or create a Person class to include both of these attributes, but you can't add two elements in the space of one, like you are attempting to do with your code above.
If you go with the Person class route, iterate through each element, and check if Person.year or whatever you choose to call the attribute is less than 1950.
If you go with the String route, iterate through each, split the String on a space to create an array, where the first element is the name and the second is the year, parse an int out of the year String using Integer.parseInt and then check if the year is less than 1950. As #Michael mentioned, combining two strings like this is not recommended
Edit: As for your new problem, Java's LinkedList<T> class is known as a generic class, because it takes a type parameter, such as the Person part in LinkedList<Person>. Because your class is not defined as a generic class, and has the same name as the built-in LinkedList, you are receiving this error when you try to pass in a type parameter, as Java thinks you are trying to use your own LinkedList class. In general, even if you are not using a particular built-in class in your code, it's best not to name your own classes with the same name as built-ins, so collisions like this don't happen. Simply rename your own class, and your code will work
Yes you can create a custom list here is the code,
create a class name it what ever you want, i named it HomeDataModel
public class HomeDataModel {
private String name;
private int year;
public HomeDataModel() {
}
public HomeDataModel(String name,int year) {
name=name;
year= year;
}
public String getName() {
return name;
}
public void setName(String name) {
name= name;
}
public String getYear() {
return year;
}
public void setYear(int year) {
year= year;
}
}
now in your activity where you want to use list,,
//creating a custom list
List<HomeDataModel> listname = new ArrayList<>();
list.add(new HomeDataModel("yourname", "Youryear"));
//code for check how is below 1950
for(int i=0; i<listname.size(); i++){
int check = list.get(i).getYear();
if(check <1950){
String newname = list.get(i).getName(); //the name is stored
Toast.makeText(MapsActivity.this,newname, Toast.LENGTH_SHORT).show();
}
}
There are errors when I am running the code: LinkedList : [Person#6d06d69c, Person#7852e922, Person#4e25154f, Person#70dea4e]
Every class in Java has the toString() method in it by default, which is called if you pass some object of that class to System.out.println(). By default, this call returns the className#hashcode of that object.
Here you have not overridden the toString method that's why it is printing like that by default.Please us below code:
public class Test {
static class Person
{
String name;
int year;
public Person(String name, int year) {
this.name = name;
this.year = year;
}
#Override
public String toString() {
return "Person [name=" + name + ", year=" + year + "]";
}
}
public static void main (String[] args) throws java.lang.Exception
{
LinkedList<Person> persons = new LinkedList<Person>();
persons.add(new Person("Joe", 2010));
persons.add(new Person("Jane", 2012));
persons.add(new Person("Charly", 1910));
persons.add(new Person("Daisy", 1908));
for (Person person : persons) {
System.out.println("Name is::"+person.name+" year is:::"+person.year);
}
//for printing the person override tostring method
System.out.println(persons);
}
}

How to use setter to set a value to a attribute which is a private array?

I had made an array of roll number so how to give a user input using setter to the private attribute which is roll number.
I made an object of class Students which is a students and tried thisstudents.for(int i=0;i<n;i++)
{(setRollno[i](sc.next()))};
But it did not worked.
class Students{
private String[] rollno = new String[1000];
private int[] intel = new int[1000];
private int[] type = new int[1000];
private String[] name = new String[1000];
public void setRollno(String[] rollno) {
this.rollno = rollno;
}
public void setName(String[] name) {
this.name = name;
}
public void setIntel(int[] intel) {
this.intel = intel;
}
public void setType(int[] type) {
this.type = type;
}
public String[] getRollno() {
return rollno;
}
public String[] getName() {
return name;
}
public int[] getIntel() {
return intel;
}
public int[] getType() {
return type;
}
}
Possibly I'm misunderstanding the aim of your data structure, but it sounds like you're trying to create a collection of student data all in one place. If this is the case then I'd strongly recommend creating a Student class which represents just one student at a time, and then using one or more standard types from the Java Collection Framework to make it easy to find a particular student.
For example, your Student class could simply contain fields which hold the roll number, name, and other data for one student. Then, assuming that you'll want to find students quickly by roll number you could create a Map<String, Student> where the map keys are roll numbers and the corresponding map value is the student who has that roll number. Simply put a new Student object into the Map after constructing it. If you need to find students by name then you could create a Map<String, Collection<Student>> (because more than one student might have the same name) and put each new Student object into this name map after constructing it.
This is likely to lead to code which is a lot easier to read, maintain, and use than an all-in-one custom collection class such as the one shown in your question.
As a rough code example:
String rollNumber = getNewRollNumber(); // wherever roll numbers come from
String name = getStudentName(); // wherever the name comes from
Student newStudent = new Student(rollNumber, name, etc);
studentsByRollNumber.put(rollNumber, newStudent);
studentsByName.computeIfAbsent(name,
n -> new ArrayList<>(1)).add(student);
Student studentWithParticularRollNumber =
studentsByRollNumber.get("123456");
Collection<Student> studentsWithParticularName =
studentsByName.get("Perry, Fred");
The Map#computeIfAbsent method will create a new ArrayList under the given student name only if no entry already exists under that name, or will fetch the existing list if that name already exists in the map, and then will put the new student into the list.
Within the call to computeIfAbsent the lambda expression t -> new ArrayList<>(1) simply means "take the value of the map key, and whatever it is just create a new ArrayList of size one". It simply guarantees that if there is not already a Collection<Student> stored under the given student name then a new ArrayList<Student> will be created and stored there.
setRollno[i](sc.next()); isn't the good syntax. Your function setRollno take an array of strings as parameter, and change all the array you have. If that's what you want, you must pass an array of Strings as parameter:
If you want to set one specific String in your rollno, you must create another function:
setRollNoAtIndex(int i, String s) {
this.rollno[i] = s;
}
If you need to call this in a loop, you can then simply do:
for(int i=0; i < n ;i++) {
students.setRollNoAtIndex(i, sc.next());
}
As per Berger's comment:
The syntax you were trying to use was probably either:
for(int i=0; i < n ;i++) {
students.getRollno()[i] = sc.next();
}
or
String[] list = new String [1000];
for(int i=0; i < n ;i++) {
list[i] = sc.next();
}
students.setRollno(list);
I think that design of this class is not correct, because we have access to internal arrays directly. Moreover, in that case you do not have to init all these arrays on new instance creation. I offer a little bit another implementation of this class, that I found more suitable for this goal:
final class Students {
private static final int TOTAL = 1000;
private final Map<String, Student> students = new HashMap<>(TOTAL);
public void setName(String rollno, String name) {
getOrCreateStudent(rollno).name = name;
}
public void setIntel(String rollno, int intel) {
getOrCreateStudent(rollno).intel = intel;
}
public void setType(String rollno, int type) {
getOrCreateStudent(rollno).type = type;
}
public Set<String> getRollno() {
return students.keySet();
}
public String getName(String rollno) {
return students.getOrDefault(rollno, Student.NULL).name;
}
public int getIntel(String rollno) {
return students.getOrDefault(rollno, Student.NULL).intel;
}
public int getType(String rollno) {
return students.getOrDefault(rollno, Student.NULL).type;
}
private Student getOrCreateStudent(String rollno) {
Student student = students.get(rollno);
if (student == null)
students.put(rollno, student = new Student(rollno));
return student;
}
private static final class Student {
private static final Student NULL = new Student(null);
private final String rollno;
private int intel;
private int type;
private String name;
public Student(String rollno) {
this.rollno = rollno;
}
}
}

How to sort an ArrayList of type Student? [duplicate]

I have simple class
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
and List<ActiveAlarm> con. How to sort in ascending order by timeStarted, then by timeEnded? Can anybody help? I know in C++ with generic algorithm and overload operator <, but I am new to Java.
Using Comparator
For Example:
class Score {
private String name;
private List<Integer> scores;
// +accessor methods
}
Collections.sort(scores, new Comparator<Score>() {
public int compare(Score o1, Score o2) {
// compare two instance of `Score` and return `int` as result.
return o2.getScores().get(0).compareTo(o1.getScores().get(0));
}
});
With Java 8 onwards, you can simply use lambda expression to represent Comparator instance.
Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });
Either make ActiveAlarm implement Comparable<ActiveAlarm> or implement Comparator<ActiveAlarm> in a separate class. Then call:
Collections.sort(list);
or
Collections.sort(list, comparator);
In general, it's a good idea to implement Comparable<T> if there's a single "natural" sort order... otherwise (if you happen to want to sort in a particular order, but might equally easily want a different one) it's better to implement Comparator<T>. This particular situation could go either way, to be honest... but I'd probably stick with the more flexible Comparator<T> option.
EDIT: Sample implementation:
public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
#Override
public int compare(ActiveAlarm x, ActiveAlarm y) {
// TODO: Handle null x or y values
int startComparison = compare(x.timeStarted, y.timeStarted);
return startComparison != 0 ? startComparison
: compare(x.timeEnded, y.timeEnded);
}
// I don't know why this isn't in Long...
private static int compare(long a, long b) {
return a < b ? -1
: a > b ? 1
: 0;
}
}
JAVA 8 and Above Answer (Using Lambda Expressions)
In Java 8, Lambda expressions were introduced to make this even easier! Instead of creating a Comparator() object with all of it's scaffolding, you can simplify it as follows: (Using your object as an example)
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);
or even shorter:
Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));
That one statement is equivalent to the following:
Collections.sort(list, new Comparator<ActiveAlarm>() {
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return a1.timeStarted - a2.timeStarted;
}
});
Think of Lambda expressions as only requiring you to put in the relevant parts of the code: the method signature and what gets returned.
Another part of your question was how to compare against multiple fields. To do that with Lambda expressions, you can use the .thenComparing() function to effectively combine two comparisons into one:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted
.thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);
The above code will sort the list first by timeStarted, and then by timeEnded (for those records that have the same timeStarted).
One last note: It is easy to compare 'long' or 'int' primitives, you can just subtract one from the other. If you are comparing objects ('Long' or 'String'), I suggest you use their built-in comparison. Example:
Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );
EDIT: Thanks to Lukas Eder for pointing me to .thenComparing() function.
We can sort the list in one of two ways:
1. Using Comparator : When required to use the sort logic in multiple places
If you want to use the sorting logic in a single place, then you can write an anonymous inner class as follows, or else extract the comparator and use it in multiple places
Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
public int compare(ActiveAlarm o1, ActiveAlarm o2) {
//Sorts by 'TimeStarted' property
return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
}
//If 'TimeStarted' property is equal sorts by 'TimeEnded' property
public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
}
});
We can have null check for the properties, if we could have used 'Long' instead of 'long'.
2. Using Comparable(natural ordering): If sort algorithm always stick to one property:
write a class that implements 'Comparable' and override 'compareTo' method as defined below
class ActiveAlarm implements Comparable<ActiveAlarm>{
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(long timeStarted,long timeEnded) {
this.timeStarted=timeStarted;
this.timeEnded=timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
public int compareTo(ActiveAlarm o) {
return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}
public int doSecodaryOrderSort(ActiveAlarm o) {
return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}
}
call sort method to sort based on natural ordering
Collections.sort(list);
In java8+ this can be written in single line as follows:
collectionObjec.sort(comparator_lamda) or comparator.comparing(CollectionType::getterOfProperty)
code:
ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
or
ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))
public class ActiveAlarm implements Comparable<ActiveAlarm> {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public int compareTo(ActiveAlarm a) {
if ( this.timeStarted > a.timeStarted )
return 1;
else if ( this.timeStarted < a.timeStarted )
return -1;
else {
if ( this.timeEnded > a.timeEnded )
return 1;
else
return -1;
}
}
That should give you a rough idea. Once that's done, you can call Collections.sort() on the list.
Since Java8 this can be done even cleaner using a combination of Comparator and Lambda expressions
For Example:
class Student{
private String name;
private List<Score> scores;
// +accessor methods
}
class Score {
private int grade;
// +accessor methods
}
Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);
Java-8 solution using Stream API:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded))
.collect(Collectors.toList());
B. When timeStarted and timeEnded have public getter methods:
List<ActiveAlarm> sorted =
list.stream()
.sorted(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded))
.collect(Collectors.toList());
If you want to sort the original list itself:
A. When timeStarted and timeEnded are public (as mentioned in the requirement) and therefore do not (need to) have public getter methods:
list.sort(Comparator.comparingLong((ActiveAlarm alarm) -> alarm.timeStarted)
.thenComparingLong((ActiveAlarm alarm) -> alarm.timeEnded));
B. When timeStarted and timeEnded have public getter methods:
list.sort(Comparator.comparingLong(ActiveAlarm::getTimeStarted)
.thenComparingLong(ActiveAlarm::getTimeEnded));
Guava's ComparisonChain:
Collections.sort(list, new Comparator<ActiveAlarm>(){
#Override
public int compare(ActiveAlarm a1, ActiveAlarm a2) {
return ComparisonChain.start()
.compare(a1.timestarted, a2.timestarted)
//...
.compare(a1.timeEnded, a1.timeEnded).result();
}});
We can use the Comparator.comparing() method to sort a list based on an object's property.
class SortTest{
public static void main(String[] args) {
ArrayList<ActiveAlarm> activeAlarms = new ArrayList<>(){{
add(new ActiveAlarm("Alarm 1", 5, 10));
add(new ActiveAlarm("Alarm 2", 2, 12));
add(new ActiveAlarm("Alarm 3", 0, 8));
}};
/* I sort the arraylist here using the getter methods */
activeAlarms.sort(Comparator.comparing(ActiveAlarm::getTimeStarted)
.thenComparing(ActiveAlarm::getTimeEnded));
System.out.println(activeAlarms);
}
}
Note that before doing it, you'll have to define at least the getter methods of the properties you want to base your sort on.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
public ActiveAlarm(String name, long timeStarted, long timeEnded) {
this.name = name;
this.timeStarted = timeStarted;
this.timeEnded = timeEnded;
}
public long getTimeStarted() {
return timeStarted;
}
public long getTimeEnded() {
return timeEnded;
}
#Override
public String toString() {
return name;
}
}
Output:
[Alarm 3, Alarm 2, Alarm 1]
Employee POJO Class
package in.ac.adit.oop.sort;
public class Employee {
private int id;
private String name;
private String department;
public int getId() {
return id;
}
public Employee() {
super();
}
public Employee(int id, String name, String department) {
super();
this.id = id;
this.name = name;
this.department = department;
}
#Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]";
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Employee Class To Manage Employee
package in.ac.adit.oop.sort;
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String[] args) {
/*
* Create 10 Employee Object
*/
Employee emp1 = new Employee(1, "Nayan", "IT");
Employee emp2 = new Employee(2, "Siddarth", "CP");
Employee emp3 = new Employee(3, "Samarth", "AE");
Employee emp4 = new Employee(4, "Bhavesh", "CV");
Employee emp5 = new Employee(5, "Sam", "FT");
Employee emp6 = new Employee(6, "Keyur", "IT");
Employee emp7 = new Employee(7, "Bala", "ME");
Employee emp8 = new Employee(8, "Mitul", "ME");
Employee emp9 = new Employee(9, "Kamlesh", "EE");
Employee emp10 = new Employee(10, "Piyush", "EE");
/*
* List of Employee Object
*/
List<Employee> employeeList = new ArrayList<Employee>();
employeeList.add(emp1);
employeeList.add(emp2);
employeeList.add(emp3);
employeeList.add(emp4);
employeeList.add(emp5);
employeeList.add(emp6);
employeeList.add(emp7);
employeeList.add(emp8);
employeeList.add(emp9);
employeeList.add(emp10);
CustomObjectSort customObjectSort = new CustomObjectSort();
List<Employee> sortByDepartment = customObjectSort.sortByDepartment(employeeList);
/*
* Sorted By Department
*/
for (Employee employee : sortByDepartment) {
System.out.println(employee);
}
/*
* Sorted By Name
*/
List<Employee> sortByName = customObjectSort.sortByName(employeeList);
for (Employee employee : sortByName) {
System.out.println(employee);
}
/*
* Sorted By Id
*/
List<Employee> sortById = customObjectSort.sortById(employeeList);
for (Employee employee : sortById) {
System.out.println(employee);
}
}
}
Custom Sorting
package in.ac.adit.oop.sort;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CustomObjectSort {
public List<Employee> sortByName(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getName().compareTo(employee2.getName());
}
});
return employeeList;
}
public List<Employee> sortByDepartment(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getDepartment().compareTo(employee2.getDepartment());
}
});
return employeeList;
}
public List<Employee> sortById(List<Employee> employeeList) {
Collections.sort(employeeList, new Comparator<Employee>() {
#Override
public int compare(Employee employee1, Employee employee2) {
return employee1.getId() - employee2.getId();
}
});
return employeeList;
}
}
You can use Collections.sort and pass your own Comparator<ActiveAlarm>
In java you need to use the static Collections.sort method. Here is an example for a list of CompanyRole objects, sorted first by begin and then by end. You can easily adapt for your own object.
private static void order(List<TextComponent> roles) {
Collections.sort(roles, new Comparator() {
#Override
public int compare(Object o1, Object o2) {
int x1 = ((CompanyRole) o1).getBegin();
int x2 = ((CompanyRole) o2).getBegin();
if (x1 != x2) {
return x1 - x2;
} else {
int y1 = ((CompanyRole) o1).getEnd();
int y2 = ((CompanyRole) o2).getEnd();
return y2 - y1;
}
}
});
}
You can call Collections.sort() and pass in a Comparator which you need to write to compare different properties of the object.
As mentioned you can sort by:
Making your object implement Comparable
Or pass a Comparator to Collections.sort
If you do both, the Comparable will be ignored and Comparator will be used. This helps that the value objects has their own logical Comparable which is most reasonable sort for your value object, while each individual use case has its own implementation.
public class ActiveAlarm {
public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;
}
List<ActiveAlarm> con = new ArrayList<ActiveAlarm>();
Collections.sort(con , (a1, a2) -> a1.timeStarted.compareTo(a2.timeStarted));
Collections.sort(con , (a1, a2) -> a1.timeEnded.compareTo(a2.timeEnded));
Here's what did the trick for me.
Was much shorter and easier than everything else I found:
Collections.sort(listName, Comparator.comparing(Object::getProperty).reversed());
The ".reversed()" part at the end was a requirement for my specific project but I'm sharing it too, as it took a while to find it
The best and the easiest way to sort any list of objects in Java (Java 8 and above).
Lets sort a basket of fruits based on the property "fruitName"
Fruit POJO:
class Fruit
{
int price;
String fruitName;
public Fruit(int price, String fruitName) {
super();
this.price = price;
this.fruitName = fruitName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
#Override
public String toString() {
return "Fruits [price=" + price + ", fruitName=" + fruitName + "]";
}
}
Now lets add fruits into a list and then sort it
List<Fruit> basketOfFruits = new ArrayList<>();
basketOfFruits.add(new Fruit(123, "oranges"));
basketOfFruits.add(new Fruit(45, "nectarine"));
basketOfFruits.add(new Fruit(369, "blueberries"));
basketOfFruits.add(new Fruit(248, "apple"));
basketOfFruits.add(new Fruit(968, "peaches"));
basketOfFruits.add(new Fruit(436, "grapes"));
basketOfFruits.add(new Fruit(596, "figs"));
//sorting by the property fruitName
Collections.sort(basketOfFruits, (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());});
You can now print the list (i.e basketOfFruits) and the fruits in the list would be sorted in ASCENDING order (lexicographically).
The output would look like this:
[Fruits [price=248, fruitName=apple], Fruits [price=369, fruitName=blueberries], Fruits [price=596, fruitName=figs], Fruits [price=436, fruitName=grapes], Fruits [price=45, fruitName=nectarine], Fruits [price=123, fruitName=oranges], Fruits [price=968, fruitName=peaches]]
Instead of Collections.sort(), Java streams can also be used (Java 8 and above). The following is the code using Java streams
List<Fruit> sortedFruits = basketOfFruits.stream().sorted( (f1, f2)->{return f1.getFruitName().compareTo(f2.getFruitName());}).collect(Collectors.toList());
here the list is sorted in the same manner as Collections.sort(), but the sorted items would be stored/collected in another list "sortedFruits". So, if we want to print the sorted items of the list, we need to print "sortedFruits" instead of "basketOfFruits" in this case

Half completed codes for arraylist

I am having my final exam tomorrow so i am practicing some questions.But i am stuck at this question.I am given a person class file and a half completed quiz10 file whereby i have to fill up.The quiz10 codes are halfway done(given).
I need to implement a function findPersonWhoseNameStartWith which returns the names of the persons in the list who start with A. But i have no idea how.
Output wanted:
result:April,Adam
public class Person{
private int age;
private String name;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public int getAge(){
return age;
}
public String getName(){
return name;
}
public String toString(){
return "" + name;
}
}
Half given codes(I have indicate which part i have attempted):
import java.util.*;
public class Quiz10{
public static void main(String[] args){
ArrayList<Person>list=new ArrayList<Person>();
list.add(new Person("April",9));
list.add(new Person("Adam",3));
list.add(new Person("bil",9));
list.add(new Person("cpril",9));
list.add(new Person("dpril",9));
ArrayList<Person>result=findPersonWhoseNameStartWith(list,"A");
System.out.println("result:");
//START DOING FROM HERE
for(int i=0;i<list.size();i++){
Person p=list.get(i);
if(p.findPersonWhoseNameStartWith("A");
}
}
You are on the right track. you are right you have to iterate over the list. Now for each entry output it if it starts with 'A'. It's very simple and a single if statement way easier than what you imagine it seems.
// pass your personList and the prefix, return a list of person starting with the prefix you specified
private List<Person> findPersonWhoseNameStartWith(List<Person> personList, String prefix) {
// create a list to store your result
List<Person> matchedList = new ArrayList<Person>();
// TODO iterate personList
// add them to the matchedList if the prefix matches
return matchedList;
}
public List<Person> findAPersonWhoStartsWith(List<Person> persons, String aLetter){
List<String> personsNames = new ArrayList<String>();
if(persons!=null && aLetter!=null && !aLetter.isEmpty()){
for(Person aPerson:persons){
if(aPerson.getName().startsWith(aLetter)){
personsNames.add(aPerson);
}
}
}
return personsNames;
}

Categories

Resources