May I know how can I sort a List<Object[]> and order by more than one element ?
below is my code:
I retrieve my result from database using below code
public List<Object[]> readyToPrint() {
Query query = em.createNativeQuery("SELECT
so_order_no,so_bo_suffix,shortname1,ETD......;
List<Object[]> allObject = query.getResultList();
return allObject;
}
As what I know I can only read the result using Object am I right ? So i think i don't have any specific class. Then if the result of element[X] meet certain condition, I want to edit the content of that element, and then only I resorting the result again.
Then i retrieve my result using below code:
`List<Object[]> allList = salesOrderFacade.readyToPrint();
readyToPrintResult = new ArrayList<>();
for (Object[] list : allList) {
if (outgoingFacade.checkReadyToDelivery(list[0].toString(), list[1].toString())) {
readyToPrintResult.add(list);
}
}
I want to sort myreadyToPrintResult` list by element 2 and follow by element 3.
I tried the code below;
Collections.sort(readyToPrintResult, new Comparator<Object[]>() {
#Override
public int compare(Object[] lines1, Object[] lines2) {
return lines1[2].xxxxx;
}
});
but I stuck in the return part. I not able to use "compare" code.
Example:
I have a List of result :
-Apple , 11-01-2017 , Y , N
-Bubble ,11-01-2017 , Y ,N
-Cat , 11-01-2017 , Y ,N
-Dora , 11-01-2017 , N ,Y
-Elephant,11-01-2017, N,Y
Then if Elephant meet some condition, I want to change the list of result of elephant to :
Elephant,11-01-2017, Y,N
Then I would like to sorting the whole list and my expected result is as below:
-Apple , 11-01-2017 , Y , N
-Bubble ,11-01-2017 , Y ,N
-Cat , 11-01-2017 , Y ,N
-Elephant,11-01-2017, Y,N
-Dora , 11-01-2017 , N ,Y
Anyone can help?
Thanks in advance
Replace ActualType with any type you expect that is Comparable (I suppose it most likely would be String):
readyToPrintResult.sort((o1, o2) -> {
int res = ((ActualType) o1[2]).compareTo((ActualType) o2[2]);
return res != 0 ? res : ((ActualType) o1[3]).compareTo((ActualType) o2[3]);
});
By declaring the Object type in the Comparator declaration, you get two Object parameters to compare in the compare() method.
So, you can invoke only Object methods on them and besides Object doesn't implement the Comparable interface.
With the Object declared class, finally,you have not a lot of way to exploit it but a tricky use of the toString().
Whereas the error :
But I got stuck on the return part. I'm not able to use compare code
return lines1[2].xxxxx;
You have two ways :
you work with more specific class than Object[]. For example : Line[] (as you name it in this way).
In this way, you may specify the Line type in the Comparator declaration :
Collections.sort(readyToPrintResult, new Comparator<Line[]>() {
#Override
public int compare(Line[] lines1, Line[] lines2) {
return lines1[2].getValue().compareTo(lines2[2].getValue());
}
});
It is the finer solution.
If you cannot work with a more specific class than Object[] because you manipulate objects with distinct(and not derived) classes , you could check the type of the two parameters and cast them in the compare() method.
It is a really not advised way because you will have to perform a a lot of boiler plate code, casts and handling the cases when the two values doesn't rely on the same type.
The int returned by the compare code is based on your parameters.
If the first one (lines1[2]) is less than your second parameter (lines2[2]) then your compare method should return a negative integer.
If lines1[2] is greater than lines2[2] you return a positive integer.
If lines1[2] and lines2[2] are the same you could return 0 (and quit comparing these objects) or as you want it compare lines1[3] against lines2[3]. Here you have to check again and then return a negative or positive number or 0.
Related
I am trying to construct a predicate that will succeed if any of the elements of a List, referenced by a Path<List<X>>, satisfy equality for one of the members of X.
However, I cannot determine whether the data can be directly accessed. None of the methods I saw allow access to that data, and I cannot use the existing expression methods to do the above.
Here is code of what I'd like to be able to do, to do this comparison based on the y attribute of the X class:
List<X> xPredicates = new ArrayList<X>();
for(X x : this.getX()) {
for(X x2: m.get("xList").getActualList()) {
xPredicates.add(cb.like(x2.y, x.y));
}
}
Predicate actualPredicate = cb.or(xPredicates);
Its not duplicated i have read all and nothing suite in my case so please read it and answer it.I have two arrays.One is Vehicle and the other is pin.This is a part of code and it is only the method.
First question :
if i have declare the arrays on the same main out of
this method the way i pass them on the method is right?With other words the parameteres
are good or need (int vehicle[],int pin[]) or something else?
Second question +=
i dont know what it does but i think that in the array pin it takes
as an ecample the pin[1] cost has 10.The number 10 is taken by
getcostosvehicle();(we put it from userinput) so when the array fills
and it hasnt any slot then the costs will be finished.As a result will
have lets say the ended slot is 20 in pin[20] lets say it has 350.The
return statement will give us only the last cost?It would be better to
write return pin[i]; so in that way it will return all the pin with
the whole costs of each one slot,am i right?
Third question
On this code and that i want to write me as an answer could you return
two arrays?I mean return pin[i],vehicle[i]; not only return pin[i];.If
yes,could you do an answer and doesnt need to fill in the vehicle
array.Just to show me if this can happen.
public static int getallcosts(vehicle[],pin[]) {
int costos = 0;
for(int i =0; i < pin.length; i++) {
costos += pin[i].getcostosvehicle();
}
return costos;
}
if i have declare the arrays on the same main out of this method the way i pass them on the method is right?With other words the parameteres are good or need (int vehicle[],int pin[]) or something else?
I'm not sure I understand you correctly but of course getallcosts(vehicle[],pin[]) won't compile, i.e. you need to define the type of the arrays (or the names if vehicle and pin would actually be the types).
It would be better to write return pin[i]; so in that way it will return all the pin with the whole costs of each one slot,am i right?
No, you can only have one return value. If you want to return multiple values then you need to wrap them in an object (array, list, pojo, etc.).
On this code and that i want to write me as an answer could you return two arrays?
See the part above: if you want to return multiple arrays you need to add them so some object and return that object. Since you didn't provide the types for the arrays I'll use another example:
class Result {
String[] strings;
int[] numbers;
}
Result someMethod() {
Result r = new Result();
r.strings = new String[]{"a","b","c"};
r.numbers= new int[]{1,2,3};
return r;
}
First question:
If you are calling a method (so you're not defining it) yuo can write parameters as you do, without type.
Otherwise you need to specify type. In this case you are defining a new method so you need to specify type of parameters.
Second question:
'+=' it's like write
costos = costos + pin[i].getcostosvehicle();
So you will add to the current value of 'costos' the 'costos' of vehicle retrieved by 'getcostosvehicle()';
Third question:
As i know you can't return two Objects of any type in return statement.
So you'll need to reorganize your code to do operation first on an array and return it and then on the other one and return it.
For example you can do a method that have as parameter a generica array do some logic inside and then return it. You will call this method for the first array and then for the second.
Example:
public int[] method(int[] array){
/*do something
*/
return array;
}
Then you will call:
firstArray = method(firstArray);
secondArray = method(secondArray);
If you want more, or i have to change something comment please.
I have one doubt if this is or is not a good practice.
So immagine that you need to concatenate not defined number of arrays, and then at the end print the result. So immagine that you can call calculate a lot of times.
E.g.
Object[] example = new Object [0];
public Object methodAppend(Object[] a, Object[] b){
- here append the array b to the array a
- return the array a
}
public Object calculate(){
Object[] someArray = new Object[5]
// immagine i already have some values in the array
for(int i=0;i<5;i++)
example = methodAppend(example,someArray)
return example
}
I get the wanted result. But my questions are:
Is this
example = methodAppend(example,someArray)
a good practice?
How is called when I send the result of the method again in the
method?
Is this one example of recursion?
Because for recursion I always thought that is when e.g. for result we call the method again.
tnx
Is this bad practice?
Absolutely not. This pattern is widely used and accepted just like any form of x = x + someCall()
How is called when I send the result of the method again in the method?
method call is evaluated using current value of your variable.
method result is set as new value of your variable
on next iteration, the value from last call is now current value
. . .
Is this one example of recursion?
No. It would only be recursive, if you'd call someMethod() from within someMethod() like
public int someMethod( int i) {
if(i < 2) {
return 1;
} else {
return someMethod(i-1)+someMethod(i-2);
}
}
Like the title says, I have an ArrayList in java with Objects. The Objects are basically room types in a hotel. they all have a typename, amount of beds etc. Now my problem is, I need to find two objects with the same value for the typename field. I got as far as looping through the list with a for loop but cant figure out how to continue. Here's my code:
import java.util.ArrayList;
public class KamerType {
private String typeNaam;
private int aantalBedden;
private double prijsPerNacht;
public KamerType(String tN, int aB, double pPN){
typeNaam = tN;
aantalBedden = aB;
prijsPerNacht = pPN;
}
public String toString(){
String s = "De kamer van type " + typeNaam + " heeft " + aantalBedden + " bedden en kost " + prijsPerNacht + " euro.";
return s;
}
public static void main(String a[]){
ArrayList<KamerType> kamertypes = new ArrayList<KamerType>();
KamerType k1 = new KamerType("Standaard", 2, 60.0);
kamertypes.add(k1);
KamerType k2 = new KamerType("DeLuxe", 2, 85.0);
kamertypes.add(k2);
KamerType k3 = new KamerType("DeLuxe", 4, 125.0);
kamertypes.add(k3);
KamerType k4 = new KamerType("Hiker", 2, 35.0);
kamertypes.add(k4);
System.out.println("Dit zijn de kamertypen:");
for(KamerType KT : kamertypes){
System.out.println(KT.toString());
}
System.out.println("\nTesten op zelfde typenaam:");
for(KamerType KT : kamertypes){
/*if(kamertypes.get(1).typeNaam == KT.typeNaam){
???
}*/
}
} // end of main
}// end of class
Any help is appreciated :)
Edit: two working answers have been given by npinti and Djorde Ivanovic, npinti gave a more guideline-ish answer. Thanks alot guys :)
Since this sounds like home work, I'll try and provide some basic guidelines as opposed to solutions.
The most basic (albeit less efficient) way would be to do a nest loop and compare the rooms:
(I assume that if an object has all 3 fields which are the same, then, I am referencing the same object. Thus, this part: AND (r1.aantalBedden != r2.aantalBedden)) AND (r1.prijsPerNacht != r2.prijsPerNacht) would help me avoid saying that I have a duplicate (when comparing the same object).
for each KamerType r1 in kamertypes
for each KamerType r2 in kamertypes
if(((r1.typeNaam.equals(r2.typeNaam)) AND (r1.aantalBedden != r2.aantalBedden)) AND (r1.prijsPerNacht != r2.prijsPerNacht))
print("We have duplicates");
An alternative, more standard (if you will) way of doing it would be to:
Make your KamerType class override the equals method, and change it such that two KamerType objects are the same if they have the same typeNaam field.
Use a data structure such as a Set (which does not allow duplicates) and place your KamerType objects in it. This will internally invoke the equals method and if it yields true, then, it will nod add the room to the set, thus allowing you to end up with a list of KamerType objects which are unique.
As a minor note, I also noticed this in your code: if(kamertypes.get(1).typeNaam == KT.typeNaam). In Java, string comparison is done through the equals method, so that should become if(kamertypes.get(1).typeNaam.equals(KT.typeNaam)).
EDIT: As per your comment, the second approach would allow you to solve the problem by going once through the list. There would also be a third approach to solve this problem however I think that it is the worst part of both solutions I provided above (slightly complicated to implement, and the execution might take longer).
Make your KamerType class implement the Comparable interface. This will force you to implement the compareTo()* method. In your implementation, you simply (in this case at least) compare the typeNaam. Then sort the list.
Once that you will have your sorted list, start from the second element of your list and compare it with the previous one. Since your list is sorted by typeNaam, any two objects which have the same typeNaam field will be exactly next to each other in your list, so you would be able to find duplicates without having a O^2 time complexity.
This will allow you to call Collections.sort() and make it sort your collection in a way you want it.
to compare strings, use 'equals' function instead of '=='
like this
if(kamertypes.get(1).typeNaam.equals(KT.typeNaam))
First create a getter method for your field:
public String getTypeNaam() {
return typeNaam;
}
Then you can compare the two values:
if(kt1.getTypeNaam().equals(kt2.getTypeNaam)) {
// Name of kt1 and kt2 is identical
}
If you want to compare each object which each other, use nested loops:
for(KamerType kt1 : kamertypes){
for(KamerType kt2 : kamertypes) {
if(kt1.getTypeNaam().equals(kt2.getTypeNaam)) {
// Name of kt1 and kt2 is identical
}
}
}
Be aware that this also finds two identical objects because they of course have the same name. You can exclude those by adding the condition kt1 != k2 to your if.
Here is what you need. First add getter for your private fields. I used loops with i and j to avoid duplicating.
for(int j = 0;j<kamertypes.size();j++){
for(int i = j+1;i<kamertypes.size();i++){
if(kamertypes.get(j).getTypeNaam().equals(kamertypes.get(i).getTypeNaam()) && i!=j){
System.out.println(kamertypes.get(j) + " and " +kamertypes.get(i));
}
}
}
I have a TreeMap with a number of entries.
TreeMap<Long, List<Payment>> myPaymentsForYear;
To remove the first week from the Map, I do
private void removeDaysFromPast() {
for (int i = 0; i < WEEK; i++) {
long key = myPaymentsForYear().firstKey();
myPaymentsForYear.remove(key);
}
System.out.println( "date: " + new Date(myPaymentsForYear.firstKey()).toString());
}
However, the printed statement always shows that the firstKey has not been removed. I fact, non of the seven elements is removed. Does anyone know why?
A TreeMap remove statement will always return the object if it's successful, or a null if the key doesn't exist (given that null is an invalid key), or throw an exception. see reference . Have you verified through debugging that you are actually attempting to remove a key that exists and that your remove statement is executing?
The code I have above is completely correct. It turns out the error was entirely somewhere else.
would be nice if you could share where the error was?
In my case, I wanted the TreeMap with a long as key to be sorted in reverse order and implemented an according Comparator (which I then passed to the TreeMap in the constructor). But as the simple type "long" cannot be used in a Comparator, I had to use the object type "Long" instead:
public class LongComparatorInverted implements Comparator<Long> {
#Override
public int compare(Long lhs, Long rhs) {
return (lhs == rhs) ? 0 : (lhs < rhs) ? 1 : -1;
}
Sure, Android Studio shows you a warning on the "==", but painfully I ignored it...
With the "Long" being an object type, for sure there was no guarantee that I compare the same object when working with the TreeMap.
So the fix for me was - of course - to use equals instead:
return (lhs.equals(rhs)) ? 0 : (lhs < rhs) ? 1 : -1;
Not so easy to find, though...
So if you encounter such an error where "remove" is not working, I´d try to check first whether you use a special Comparator and fully test the Comparator before using it.