Custom comparator isn't sorting - java

I'm trying to simulate a CPU scheduler. I have an ArrayList of a Process class I made. I'm trying to sort this array list by the arrival time of the process. I must be missing something, because when I print my ArrayList, nothing happens.
I've been looking through other users posts but I haven't found anything that made sense to me.
Here is my Comparator and call to sort:
class ArrivalTimeComparator implements Comparator<Process> {
#Override
public int compare(Process p1, Process p2) {
return (int) (p1.getArrivalTime()-p2.getArrivalTime());
}
}
Collections.sort(processArray, new ArrivalTimeComparator());

This code
(int)(p1.getArrivalTime()-p2.getArrivalTime())
may suffer from integer operation overflow, thus you can get odd results. If you're using Java 7, use
Integer.compare(p1.getArrivalTime(), p2.getArrivalTime()); //or Long.compare
If you're working with Java 6 or less:
return p1.getArrivalTime() > p2.getArrivalTime() ? 1 : p1.getArrivalTime() < p2.getArrivalTime() ? -1 : 0;

Related

Bring Class Leader Id on top of the list using Java8 Streams

I have a list of students and I want to bring only the leaderId on top of the same list following remains the remaining list items using Java Streams. I tried the below logic but it is not working as expected
List<Student> students = ....
Long leaderId = 123;
students.stream().sort((s1,s2) -> leaderId.equals(s1.getId()) || leaderId.equals(s2.getId()) ? 1: 0).collect(Collectors.toList());
Can anyone please give me some suggestion on this
Example
List of students:
[{id:121, name:"John"}, {id:131, name:"Susan"}, {id:123, name:"Jacob"}, {id:155, name:"Sunny"}]
Expected Output
[{id:123, name:"Jacob"}, {id:121, name:"John"}, {id:131, name:"Susan"}, {id:155, name:"Sunny"}]
You have to write your own comparator first which places the leader at the front of the list when sorted using it. Then you have to use it for sorting the list. I don't see any point of using the streams here, since the iterative code looks more simple and readable. Here's how it looks in practice.
static class LeaderFirstComparator implements Comparator<Student> {
final long leaderId;
LeaderFirstComparator(long leaderId) {
this.leaderId = leaderId;
}
#Override
public int compare(Student o1, Student o2) {
if (o1.id == leaderId && o2.id != leaderId)
return -1;
else if (o1.id != leaderId && o2.id == leaderId)
return 1;
else
return 0;
}
}
And the client code:
students.sort(new LeaderFirstComparator(leaderId));
Update
If the first object is the leader, then it should come before the second, hence returning -1 according to the contract. Otherwise, if the second object is the leader, then the first one should come after it, hence 1. If nether of the objects are the leader or both are leaders, then the original ordering is preserved. Thus returning 0.
As per the below comment, you can further simplify it to this one liner:
students.sort(Comparator.comparing(s -> s.getId() != leaderId));
If the leader has a concrete id equals to 123, yo can get it using only a filter
List leaderStudents = students.stream().filter(s1 -> leaderId.equals(s1.getId()).collect(Collectors.toList());

Kotlin: Find Count from Nested set in List (more functional approach)

Below function creates a Map, gets the count of passengers where passengers are > minTrips. The code works completely fine. Please see below
fun List<Trip>.filter(minTrips : Int): Set<Passenger> {
var passengerMap: HashMap<Passenger, Int> = HashMap()
this.forEach { it: Trip ->
it.passengers.forEach { it: Passenger ->
var count: Int? = passengerMap.get(it)
if (count == null) {
count = 1
passengerMap.put(it, count)
} else {
count += 1
passengerMap.put(it, count)
}
}
}
val filteredMinTrips: Map<Passenger, Int> = passengerMap.filterValues { it >= minTrips }
println (" Filter Results = ${filteredMinTrips}")
return filteredMinTrips.keys
}
Even though this is written in Kotlin, it seems like the code was first written in Java and then converted over to Kotlin. If it was truly written in Kotlin I am sure this wouldnt have been so many lines of code. How can I reduce the lines of Code? What would be a more funtional approach to solve this? What function or functions can I use to extract the Passengers Set directly where Passengers are > minTrips? This is too much of a code and seems crazy. Any pointers would be helpful here.
One way you could do this is to take advantage of Kotlin's flatmap and grouping calls. By creating a list of all passengers on all trips, you can group them, count them, and return the ones that have over a certain number.
Assuming you have data classes like this (essential details only):
data class Passenger(val id: Int)
data class Trip(val passengers: List<Passenger>)
I was able to write this:
fun List<Trip>.frequentPassengers(minTrips: Int): Set<Passenger> =
this
.flatMap { it.passengers }
.groupingBy { it }
.eachCount()
.filterValues { it >= minTrips }
.keys
This is nice because it is a single expression. Going through it, we look at each Trip and extract all of its Passengers. If we had just done map here, we would have List<List<Passenger>>, but we want a List<Passenger> so we flatmap to achieve that. Next, we groupBy the Passenger objects themselves, and call eachCount() on the returned object, giving us a Map<Passenger, Int>. Finally we filter the map down the Passengers we find interesting, and return the set of keys.
Note that I renamed your function, List already has a filter on it, and even though the signatures are different I found it confusing.
You basically want to count the trips for each passenger, so you can put all passengers in a list and then group by them and afterwards count the occurences in each group:
fun List<Trip>.usualPassengers(minTrips : Int) = // 1
flatMap(Trip::passengers) // 2
.groupingBy { it } // 3
.eachCount() // 4
.filterValues { it >= minTrips } // 5
.keys // 6
Explanation:
return type Set<Passenger> can be inferred
this can be ommitted, a list of the form [p1, p2, p1, p5, ...] is returned
a Grouping is created, which looks like this [p1=[p1, p1], p2=[p2], ...]]
the number of occurences in each group will be counted: [p1=2, p2=1, ...]
all elementes with values which less than minTrips will be filtered out
all keys that are left will be returned [p1, p2, ...]
p1...pn are Passenger instances

Java: Comparison method violates its general contract

I got the exception from above which I know was discussed often here on SO. Anyways, the others don't tell me what's wrong with my code. These StyleAlbum are just Music albums. getAdded() returns the time when their last song was added to Android's MediaStore in milliseconds as int.
This happens only on some devices!
Code:
public static List<StyleAlbum> sortAdded() {
List<StyleAlbum> mAlbums = new ArrayList<>();
mAlbums.addAll(Library.getAlbums());
Collections.sort(mAlbums, new Comparator<StyleAlbum>() {
#Override
public int compare(StyleAlbum lhs, StyleAlbum rhs) {
if (lhs.getAdded() > rhs.getAdded()) {
return -1;
} else return 1;
}
});
return mAlbums;
}
Your comparator does not account for two items being equal, ie it never returns zero. You should use something like
return Integer.compare(lhs.getAdded(), rhs.getAdded());
otherwise the result is at least inconsistent, and depending on the algorithm it may even be completely wrong. In this case, Tim sort (the algorithm used in the JDK) is smarter enough to tell you that there's an error.
Note: I compared integers with Integer.compare instead of a subtraction (thanks Louis Wasserman) to avoid overflow errors
You should return 0 in the compare method if both values are the same. Especially, a comparison from an object to itself should give 0.

Comparator not functioning as intended for PriorityQueue

I wrote this comparator function to be used with a priority queue. It works fine this way, it gives the words with the least frequency when I poll().
But this is frequency and I want them to behave in the opposite way. I swapped the return values -1 and +1, and that is leads to unordered and mixed results on poll().
Why does that happen, and how to fix it? Also, why is it necessary to always specify the initial size of a PriorityQueue while specifying the comparator in the constructor? Does it have any effect that I am unable to see?
public class StringFrequencyComparator implements Comparator<Word>
{
public int compare(Word x, Word y)
{
if (x.frequency() < y.frequency())
{
return -1;
}
if (x.frequency() > y.frequency())
{
return +1;
}
return 0;
}
}
Update: I had made a mistake. I was inserting values in the PriorityQueue and then updating their frequencies. But, I was confused because in spite of this mistake the orders were perfect for the comparator and only mixed up when I swapped the -1s and 1s values forcing me towards believing there was something wrong with the comparator. I still wonder how it was perfect.

How does recursion work here?

Recursion is a new practice for me and I am trying to get better at it and understand how the methods return. I have the following program but am unfailiar with how to use the this keyword. Can you please review the code and walk me through the program showing the values held by the variables as the methods execute?
I have tried numerous things to determine how the value answer in the compute method holds 14 after execution can anyone walk me through the first few recursive calls so I can try and figure out the rest?
public class Recurs1 {
public static void main (String [] arg) {
Recurs1 r = new Recurs1();
r.compute();
}
public void compute() {
int [] stuff = {1, 2, 3, 4};
int answer = this.go(stuff, 0);
System.out.println("The answer is " + answer);
}
private int go(int[] numbers, int spot) {
if (numbers.length == spot) return spot;
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
}
Ok so a few things I notice here:
The purpose of go() seems to be calculating the sum of the numbers in the array. If this is the case, your method should look like this:
private int go(int[] numbers, int spot) {
if (numbers.length - 1 == spot) return numbers[spot];
int value = this.go(numbers, spot + 1 );
return value + numbers[spot];
}
This is because numbers.length in this case will return 4, but the last element in this array is at index 3 (arrays are 0-indexed).
This way, when the function is called with the second parameter set to 3, it will return the value of the last element in the array and then the code will "bubble up" (as I like to call it) and calculate the sum of the elements by subsequently returning the current summed value + the value of the current call.
As for your problem with the this keyword, it's actually very simple. this always refers to the current class instance your code is in. In this case, you create a Recurs1 instance called r in your main function so whenever you call a method on that particular object, the this keyword used in those methods will refer to r. If you created multiple Recurs1 objects (each with potential different internal states) in your program, their respective this references would always point to themselves allowing you to access their member variables and methods.
Hope that helps and good luck, recursion is usually what most people have trouble getting their heads around at first but once you get used to it it's pretty cool!
OK so this is not an answer to your question per se, more like a lesson in recursion.
Keep in mind I have never tried to to do this with a java class.
Recursion means a function that calls itself repeatedly until a answer has been reached, or your function detects you are running out of stack space.
You first step into the function determines if you will call yourself.
When you call yourself you will push a new copy of the data onto the stack and begin executing. I think in the case of java you will allocate a new object into the heap ( don't quote me on this ) and each invocation will have a new set of variables that get populated with new values.
As you recurse deeper and deeper you simply allocate new copies of the object until you find the answer or run out of memory.
If you find the answer you then return the result to the previous level in the stack of objects eg:
int foo(int i ){
if(some condition){
return foo(i);
} else
return i
}
as You can see if the condition tests true the foo() keeps getting called. Now at each call, the variables of foo() are saved for as many levels deep as you go. If the condition tests false then each instance of foo() returns to the previous until you are at the original invocation of foo() which then returns to the caller of foo().
Clear as Mud?

Categories

Resources