i have one class which have 4 int fields . i want to sort objects array by some mathematical operation on fields .I tried below code but sorting is not happening.
class Cust1 implements Comparable<Cust1>{
int a;
int o;
int s;
int p;
#Override
public int compareTo(Cust1 b) {
if(this.a + this.s <= b.a + b.s)
{
return 1;
}
else {
return 0;
}
}
}
public class Test5 {
public static void main (String args[]) throws Exception
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
Cust1[] cust = new Cust1[n];
for(int i=0;i<n ;i++)
{
Cust1 a = new Cust1();
String[] str = br.readLine().split(" ");
a.a = Integer.parseInt(str[0]);
a.o = Integer.parseInt(str[1]);
a.s = Integer.parseInt(str[2]);
a.p = Integer.parseInt(str[3]);
cust[i] =a;
}
Arrays.sort(cust, new Comparator<Cust1>() {
#Override
public int compare(Cust1 o1, Cust1 o2) {
return o1.compareTo(o2);
}
});
}
}
Based on your code snippet: you don't need to provide Comparator, since Cust1 already implements Comparable. So, this should be enough:
Arrays.sort(cust);
Also, Cust1 implementation of Comparable doesn't really tell, when one object is less then other. Probably, you meant something like this:
#Override
public int compareTo(Cust1 b) {
if(this.a + this.s < b.a + b.s) {
return 1;
} else if (this.a + this.s > b.a + b.s) {
return -1;
} else {
return 0;
}
}
But it's hard to tell, what exact implementation of Comparable should be without more details (for instance, for some reason fields o and p are not involved in comparison at all).
You comparator work wrong. It should return:
>0 - current object is greater than another one
0 - current object is equal to another one
<0 - current object is less than another one
class Cust1 implements Comparable {
int a;
int o;
int s;
int p;
#Override
public int compareTo(Cust1 b) {
return Integer.compare(a + s, b.a + b.s);
}
}
And you do not have to provide additional comparator to Arrays.sort() since Cust1 already implements Comparable.
Related
I want to compare a collection (ArrayList) of elements if they are the same type. In the beginning I do not know what type the elements are (generic types), so I decided to use Object type. But I still cannot compare them. The problem is in the function triplesort().The warning is:
Operator '>' cannot be applied to 'java.lang.Object', 'java.lang.Object'. If you have any possible solutions to that problem and you let me know, I would be grateful. <3
Triple.java
import java.util.ArrayList;
public class Triple<T, S, U> {
private T t;
private S s;
private U u;
private ArrayList<Object> array = new ArrayList<Object>();
Triple(T t, S s, U u) {
setT(t);
setS(s);
setU(u);
array.add(this.t);
array.add(this.s);
array.add(this.u);
}
public void setT(T t) {
this.t = t;
}
public void setS(S s) {
this.s = s;
}
public void setU(U u) {
this.u = u;
}
public T getFirst() {
return t;
}
public S getSecond() {
return s;
}
public U getThird() {
return u;
}
public String toString() {
return t + "\n" + s + "\n" + u + "\n";
}
public boolean isHomogeneous() {
return t.getClass() == s.getClass() && t.getClass() == u.getClass();
}
public void tripleSort() {
try {
for (int i = 1; i < array.size(); ++i) {
Object key = array.get(i);
int j = i - 1;
while (j > -1 && array.get(i) > key) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
There are two main issues with code you've provided:
Relational operators <, <=, >, >= can be used only to compare numeric primitive types. Obviously, you can use it with objects.
To compare reference types you can use Comparator or these objects can implement Comparable interface (i.e. they basically are aware how to compare themselves). But it doesn't make since to compare BigDecimal and Boolean, or String and HashMap, how would you approach that? For that reason, these interfaces are generic and Comparator<T> can't be used with objects of type U.
That said, your Triple<T, S, U> would not be able to do a lot with these objects belonging to different type (definitely you can't sort them).
Hence, if you need a data-carrier holding references of three distinct types, that fine. It's still can be useful, but don't expect from it much.
A Java 16 record fits in this role perfectly well:
public record Triple<T, S, U>(T first, S second, U third) {}
But if you need to able to operate with these values comparing them with one another then consider changing the Triple to hold only elements of type T.
Here's an example of how it might be implemented:
public static class Triple<T> {
private List<T> list = new ArrayList<>(3);
private Comparator<T> comp;
private Triple(T first, T second, T third, Comparator<T> comp) { // no way and no need to invoke this constructor outside the class
this.comp = comp;
Collections.addAll(list, first, second, third);
}
public static <T> Triple<T> getInstance(T first, T second, T third, Comparator<T> comp) {
Triple<T> triple = new Triple<>(first, second, third, comp);
triple.init();
return triple;
}
public void init() {
list.sort(comp);
}
public T getFirst() {
return list.get(0);
}
public T getSecond() {
return list.get(1);
}
public T getThird() {
return list.get(2);
}
public boolean isHomogeneous() {
return comp.compare(getFirst(), getSecond()) == 0
&& comp.compare(getFirst(), getThird()) == 0
&& comp.compare(getSecond(), getThird()) == 0;
}
public String toString() {
return list.stream().map(T::toString).collect(Collectors.joining("\n"));
}
}
Usage example:
Let's consider a Triple storing integer value in Descending order.
public static void main(String[] args) {
Triple<Integer> intTriple = Triple.getInstance(5, 3, 12, Comparator.reverseOrder());
System.out.println(intTriple);
}
Output:
12
5
3
It's silly problem. I have my own comparator interface, class Student - it's objects will be sorted, class BubbleSort with bubblesorting algorithm and main. I think every class except from main is written quite well, but I have problem with implementation of them in main to make my sorting to start :/ I've just created ArrayList of random Students I want to be sorted, but I have problem with BubbleSort class and have no idea, how to start.
In future (I hope it will be today :)) I will do exactly the same with another classes containing sorting algorithms like BubbleSort here. I think their implementation in main will be identical.
import java.util.Random;
import java.util.ArrayList;
public class Program {
public static void main(String[] args) {
int elements = 100000;
ArrayList<Student> list = new ArrayList<Student>();
Random rand = new Random();
for (int i=0; i<elements; i++) {
list.add(new Student(rand.nextInt(4)+2, rand.nextInt(900000)));
}
System.out.println(list);
}
}
.
import java.util.ArrayList;
public class BubbleSort {
private final Comparator comparator;
public BubbleSort(Comparator comparator) {
this.comparator = comparator;
}
public ArrayList<Student> sort(ArrayList<Student> list) {
int size = list.size();
for (int pass = 1; pass < size; ++pass) {
for (int left = 0; left < (size - pass); ++left) {
int right = left + 1;
if (comparator.compare(list.get(left), list.get(right)) > 0)
swap(list, left, right);
}
}
return list;
}
public int compare(Object left, Object right) throws ClassCastException
{ return comparator.compare(left, right); }
private void swap(ArrayList list, int left, int right) {
Object temp = list.get(left);
list.set(left, list.get(right));
list.set(right, temp);
}
}
.
public class Student implements Comparator<Student> {
int rate;
int indeks;
public Student(int ocena, int index) {
this.rate = ocena;
indeks = index;
}
public String toString() {
return "Numer indeksu: " + indeks + " ocena: " + rate + "\n";
}
public int getIndeks() {
return indeks;
}
public int getRate() {
return rate;
}
public int compare(Student left, Student right) {
if (left.getIndeks()<right.getIndeks()) {
return -1;
}
if (left.getIndeks() == right.getIndeks()) {
return 0;
}
else {
return 1;
}
}
}
.
public interface Comparator<T> {
public int compare(T left, T right) throws ClassCastException;
}
Your code looks little bit strange. You didnt mention if you have to use bubble sort so i write both my ideas
1.Without explicitly using bubble sort
You can use Collections.sort() combined with overridencompareTo() method
So your code will look like this
class Student implements Comparable<Student>{
//variables constructor methods go here
private index;
#Override
public int compareTo(Students s) {
int index = s.index;
if (this.index > index) {
return 1;
} else if (this.index == index) {
return 0;
} else {
return -1;
}
}
}
And in your main class Collections.sort(myStudents)
2.Explicitly using bubble sort
Student class
class Student{
//class variables methods constructor goes here
}
Comparator class
class StudentComparator implements Comparator<Student>{
#Override
public int compare(Student a, Student b) {
//bubble sort code goes here
}}
Main class
class MyMainClass{
public static void main(String[] args) {
public int elements = 100000;
ArrayList<Student> list = new ArrayList<Student>();
Random rand = new Random();
for (int i=0; i<elements; i++) {
list.add(new Student(rand.nextInt(4)+2, rand.nextInt(900000)));
}
Collections.sort(list, new StudentComparator());
}
Two points to make here:
a) You are not calling sort at all. You need to instantiate your BubbleSort class and actually call the method. list = new BubbleSort(new Comparator(){...}).sort(list); <-- This syntax also calls for the sort method to be static so that you don't need to make a new object for every sort. The example below sorts by index.
list = new BubbleSort(new Comparator<Student>() {
#Override
public compare(Student a, Student b) {
return a.getIndeks() - b.getIndeks();
}
}).sort(list);
Btw, this also assumes that BubbleSort is made generic, since it's easier (and kinda makes sense anyway)
b) I hope this is some kind of project where you have to show your ability to make a sorting algorithm, otherwise you should use library methods for these things
Also, while the code is not bad, you might want to show it to someone with professional Java experience (it does not conform to a lot of standards and many things can be improved and made consistent with each other), or post it to https://codereview.stackexchange.com/
I dont see you calling the bubblesort class anywhere. A list will not automatically sort its elements. Please go through this link. You ll find it handy.
http://www.programcreek.com/2013/03/hashset-vs-treeset-vs-linkedhashset/
I'm learning about comparable and am implementing it in my Inventory class. However when I go to compile the code, the compiler gives an error.
InventoryItem.java uses unchecked or unsafe operations.
Can anyone please help me out. What is wrong with my code and what can I do to fix this issue. Thank you for your help in advance.
class InventoryItem implements Comparable<InventoryItem>
{
private String name;
private int uniqueItemID;
public InventoryItem()
{
name = " ";
uniqueItemID = 0;
}
public InventoryItem(String newName, int newItemID)
{
name = newName;
uniqueItemID = newItemID;
}
public InventoryItem(InventoryItem i)
{
name = i.name;
uniqueItemID = i.uniqueItemID;
}
public void setName(String newName)
{
name = newName;
}
public void setItemID(int newItemID)
{
uniqueItemID = newItemID;
}
public int getItemID()
{
return uniqueItemID;
}
public String getName()
{
return name;
}
public int compareTo(InventoryItem i)
{
int anotherUniqueID = i.getItemID();
return (this.uniqueItemID - anotherUniqueID);
}
public static void sort(Comparable[] a, int numberUsed)
{
int index, indexOfNextSmallest;
for(index = 0; index < numberUsed - 1; index++)
{
indexOfNextSmallest = indexOfSmallest(index, a, numberUsed);
interchange(index, indexOfNextSmallest, a);
}
}
private static int indexOfSmallest(int startIndex, Comparable[] a, int numberUsed)
{
Comparable min = a[startIndex];
int indexOfMin = startIndex;
int index;
for(index = startIndex + 1; index < numberUsed; index++)
{
if(a[index].compareTo(min) < 0)
{
min = a[index];
indexOfMin = index;
}
}
return indexOfMin;
}
private static void interchange(int i, int j, Comparable[] a)
{
Comparable temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
public class InventoryItemTester
{
public static void main(String [] args)
{
InventoryItem[] items = new InventoryItem[3];
items[0] = new InventoryItem("Pens", 2);
items[1] = new InventoryItem("Pencils", 3);
items[2] = new InventoryItem("Notebooks", 1);
System.out.println("Before sorting");
System.out.println(items[0]);
System.out.println(items[1]);
System.out.println(items[2]);
InventoryItem.sort(items, items.length);
System.out.println("After sorting");
System.out.println(items[0]);
System.out.println(items[1]);
System.out.println(items[2]);
}
}
At a guess I'd say this line is causing the issue (Your compiler tells you exactly which line is the problem, this might be useful to include in your next question):
private static int indexOfSmallest(int startIndex, Comparable[] a, int numberUsed)
{
Comparable min = a[startIndex];
int indexOfMin = startIndex;
int index;
for(index = startIndex + 1; index < numberUsed; index++)
{
here==========> if(a[index].compareTo(min) < 0)
{
You are calling compareTo with a InventoryItem where it is expecting an Object. You could add a #SuppressWarnings annotation which would make it go away :)
The basic idea of Comparable and Comparator is they apply a sorting order to an Object so that the standard JDK Collections objects can do all the hard work for you.
In your case your comparesTo method does the correct thing, however I'm not sure if this is good planning or good luck, so things to note:
InventoryItem.comparesTo method needs to evaluate the current instance to the provided instance and return an integer signifying the ordering, -1 means the instance (ie this) should be ordered before the argument, 0 means they are the same and 1 means the instance is after the argument. Something like this lets the JDK do all the hard work for you
public int compareTo(InventoryItem i)
{
return Integer.valueOf(this.uniqueItemID).compareTo(i.uniqueItemID);
}
In order to use Comparable all you really need to do is implement it and then use the standard JDK Collections classes to do all the heavy lifting for you, eg:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class InventoryItemTest
{
public static void main(String [] args)
{
List<InventoryItem> items = new ArrayList<InventoryItem>();
items.add(new InventoryItem("Pens", 2));
items.add(new InventoryItem("Pencils", 3));
items.add(new InventoryItem("Notebooks", 1));
System.out.println("Before sorting");
System.out.println(items);
Collections.sort(items);
System.out.println("After sorting");
System.out.println(items);
}
}
I realise this might not be as much fun as writing your own sorting algorithms but if you want to do that with no compiler warnings then you need to start looking at generics
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have an arraylists filled with objects. Each object consists of two integers. How do i sort the arraylist based on the first integer while keeping the second integer with its original integer? And then how to I add all of the second integers of the sorted arraylist?
I tried this:
Collections.sort(info, new Comparator()
{
public int compare(M one, M two)
{
return m1.getCost().compareToIgnoreCase(m2.getCost());
}
});
class M{
//Declares the attributes belonging to this class
private int money;
private int cost;
//Constructor method
{
//this refers to object in which the method was called
this.cost = cost;
this.money = money;
}
//Returns the cost variable
public int getCost()
{
return cost;
}
public void setCost(int cost)
{
this.cost = cost;
}
//Returns the maximum amount
public int getMoney()
{
return money;
}
public void setMoney(int Money)
{
this.Money = Money;
}
}
I am new to java so any help would be greatly appreciated(:
import java.util.*;
public class M implements Comparator<M>{
int i,j;
M(int a, int b){
i=a; j=b;
}
public int compare(M m1, M m2){
return (m1.i-m2.i);
}
public boolean equals(Object o){
if(this.i==((M)o).i)
return true;
else
return false;
}
public static void main(String args[]){
M m1 = new M(2,1);
M m2 = new M(3,2);
M m3 = new M(1,3);
ArrayList<M> a = new ArrayList<M>();
a.add(m1);
a.add(m2);
a.add(m3);
Collections.sort(a,(Comparator<M>)m1);
//ArrayList a is sorted
for(int j=0;j<a.size();j++){
System.out.println(a.get(j).i);
}
}
}
Implement the Comparator interface in your class so that the Collections.sort method will sort the objects using the int1 of class M. Then use Collections.sort method to sort the array. This should answer the first part of the question.
When creating a Comparator it should be used as a Generic type with T (where T represents the objects in the array) and thus: public int compare(T a, T b) { .. }.
For instance:
new Comparator<M> {
// Note the signature
public int compare(M one, M two)
{
// Now return a correct value based on the ordering
// using one.getCost() and two.getCost()
// Obviously "compareToIgnoreCase" is wrong for use with numbers.
// Either work this out or see one of the existing/linked answers.
}
}
If generics are not used then the signature is public int compare(Object one, Object two) and casting will likely be needed - note that there is no overload for (int, int); it is a declared method that is never used!
See also:
How to sort an arraylist of objects by a property? (I have voted to close as a duplicate of this one and it shows a correct and simple way to get the ordering between two numeric values.)
Sorting an ArrayList of Contacts based on name? (Discusses another approach is to make the objects themselves implement Comparable.)
how about this :
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
M[] mm = new M[4];
mm[0] = new M(11, 2);
mm[1] = new M(11, 4);
mm[2] = new M(4, 67);
mm[3] = new M(4, 2);
mm = compareM(mm);
for (int a = 0; a < mm.length; a++) {
System.out.println("index : "+a+" a : "+mm[a].a+" b : "+mm[a].b);
}
}
public static M[] compareM(M[] data) {
for (int a = 0; a < data.length - 1; a++) {
for (int b = a + 1; b < data.length; b++) {
if (data[a].a > data[b].a) {
M temp = data[a];
data[a] = data[b];
data[b] = temp;
}
}
}
for (int a = 0; a < data.length; a++) {
int indStart = a;
int indEnd = a;
for (int b = a + 1; b < data.length; b++) {
if (data[b].a == data[a].a) {
indEnd++;
} else {
b = data.length;
}
}
a = indEnd;
for (int c = indStart; c <= indEnd; c++) {
for (int d = c + 1; d <= indEnd; d++) {
if (data[c].b > data[d].b) {
M temp = data[c];
data[c] = data[d];
data[d] = temp;
}
}
}
}
return data;
}
static class M {
public int a, b;
//u can have function to set value of a n b, or any function
public M(int ax, int bx) {
this.a = ax;
this.b = bx;
}
}
}
Is there an easy way of finding the MAX number from the list where number is stored in x.y.z format? e.g. To manage some system versions.
I have tried Collection.max(list) and that does not work.
Sample Code:
public static void main(String args[])
{
List<String> list = new ArrayList<String>();
list.add("1.0.0");
list.add("1.1.0");
list.add("1.9.0");
list.add("1.10.0");
System.out.println(Collections.max(list));
}
Expected: 1.10.0
Result: 1.9
Thanks for your time.
Try to use this one :
Collections.max(myList, new Comparator<String>() {
#Override
public int compare(String lhs, String rhs) {
String[] first = lhs.split("\\.");
String[] second = rhs.split("\\.");
for (int i = 0; i < first.length; i++) {
if(Integer.valueOf(first[i]) > Integer.valueOf(second[i])) {
return 1;
}
if(Integer.valueOf(first[i]) < Integer.valueOf(second[i])) {
return -1;
}
}
return 0;
}
});
Well for one thing, you need to ensure that Java knows they are numbers - at the moment they're just Strings, and strings sort lexigraphically (i.e. in "alphabetical order").
My approach to this would be to create a small class that implements Comparable, which will then work automatically with sorting and comparison logic. Something like this perhaps:
public class VersionNumber implements Comparable<VersionNumber> {
public final int major;
public final int minor;
public final int patch;
// Constructor etc. elided
public int compareTo(VersionNumber other) {
if (other.major != major) return major - other.major;
if (other.minor != minor) return minor - other.minor;
return patch - other.patch;
}
}
Parsing the string to create instances of this class is left as an exercise to the reader!
You may have to write a custom Comparator for comparing version number strings:
public class VersionComparator extends Comparator<String> {
#Override
public int compare(String o1, String o2) {
// Get major/minor/revison numbers by splitting strings at dots
String[] p1 = o1.split("\\.");
String[] p2 = o2.split("\\.");
// Compare major versions then minor then revision until a difference found
for(int i = 0; i < (p1.length < p2.length) ? p1.length : p2.length; i++) {
int result = Integer.valueOf(p1[i]).compareTo(Integer.valueOf(p2[i]));
if(result != 0) return result;
}
// Return zero if they're identical
return 0;
}
}
The you can use this comparator with the Collections.max function:
Collections.max(list, new VarsionComparator());
You can use version of max with the specified comparator:
System.out.println(Collections.max(list, new Comparator<String>() {
public int compare(String s1, String s2)
{
StringTokenizer st1 = new StringTokenizer(s1,".");
StringTokenizer st2 = new StringTokenizer(s2,".");
int res = 0;
String t1, t2;
while(st1.hasMoreTokens() && st2.hasMoreTokens())
{
t1 = st1.nextToken();
t2 = st2.nextToken();
res = Integer.valueOf(t1).compareTo(Integer.valueOf(t2));
}
if(res == 0)
{
res = st1.hasMoreTokens() ? 1 : (st2.hasMoreTokens() ? -1 : 0);
}
return res;
}
public boolean equals(Object obj) { return false; }
}));
This will give you 1.9 because it will not consider second number to be 10, it will treat it as 1 first and then 9
Edit
If you want to do it manually, then
Split your number on basis of "."
Check manually which number is greater.