How to compare the values of objects of a class - java

I have made an inner class- in and its constructor. In a function func() I am passing values of battery and time to the constructor as entered by the user using a Scanner, and this function is called multiple times.I want to compare the different values of battery as input by user using the class objects and then print them. lets say func is called 4 times and i pass different battery values each time. I want to check whether difference between them is greater then 1.. IF yes then print that battery value . Eg: 1st call- (98,2) 2nd call-(97,4) 3rd call(95,9) 4th call(94,11) . Here difference between 2nd and 3rd call's battery level is greater than 1, so i'll have to print the initial one i.e. 2nd call battery level and its corresponding time.How can I code that?
public class Out {
Scanner sc = new Scanner(System.in)
class in {
int x, int y;
in(int x, int y) {
this.x = x;
this.y = y;
}
}
in obj = new in(0, 0); //call this obj inside func
public void func() {
int battery = sc.nextInt();
int time = sc.nextInt();
in inner = new in(battery, time);
}
I cannot use an arraylist as func() will be called more than a thousand times so to avoid memory wastage. I have made an object obj with values 0,0 . I will compare obj's battery value to in's battery value(compare whether the difference in battery value is more than 1 or not if yes then print the previous battery value) and after that update the obj's battery value to the current value of battery(passed by user)..

Create a function to compare two objects based on what you want to measure.
public boolean InEqual(in obj1, in obj2)
{
if(obj1.x - obj2.x > 1)
return true;
else
return false;
}
or you can return the difference between the values
public int Difference(in obj1, in obj2)
{
if(obj1 != null && obj2 != null)
return obj1.x - obvj2.x;
else
return 0;
}

Related

How do I compare the variables held within two objects before returning them from an ArrayList?

I have a class, FlightDatabase which contains a number of AirJourney objects, these air journey objects have the following details: Origin airport, destination airport and number of miles in flight.
For example one AirJourney object may have Origin: A, Destination: B and miles: 400.
The following array of strings represents each AirJourney object present in the database, with the first letter being the origin, the second the destination and the third the number of miles in the flight.
"AB800", "BC900", "CD400", "DE400", "BF400", "CE300", "DE300", "EB600", "CE200", "DC700", "EB500", "FD200"
Within this string there are a number of repeated flights: DE400 and DE300 and then CE300 and CE200.
I need to be able to return AirJourney objects from the FlightDatabase and also ignore any flights that are of a higher number of miles.
The method below allows the returning of AirJourney objects from the database by using a string consisting of two letters that will match with the origin and destination airports held within the object. However this method will return the first matching object, not the one of the fewest amount of miles.
public AirJourney getFlightDetailsFromAirportPairing(String airportPair)
{
for(AirJourney journey : database)
{
String journeyPair = journey.getOriginAirport() + journey.getDestinationAirport();
if(airportPair.equals(journeyPair))
{
return journey;
}
}
return new AirJourney(0, null, null);
}
For example if I call `getFlightDetailsFromAirportPairing("DE") then the DE400 flight will be returned, when instead I want the DE300 flight to be returned and the DE400 flight is to be ignored.
I am not sure how to modify this method so that it will return the flight of the lowest amount of miles.
Maybe something like this can be used?
The idea is to store the lowest value seen, and whenever you see something with a lower value, you store the AirJourney object and the distance.
public AirJourney getFlightDetailsFromAirportPairing(String airportPair){
double lowestDistance = Double.MAX_VALUE;
AirJourney lowestDistanceAirJourney = null;
for (AirJourney journey : database) {
String journeyPair = journey.getOriginAirport() + journey.getDestinationAirport();
if(airportPair.equals(journeyPair)) {
if (lowestDistanceAirJourney == null || journey.getMiles() < lowestDistance) {
lowestDistanceAirJourney = journey;
lowestDistance = journey.getMiles();
}
}
}
return lowestDistanceAirJourney;
}
public AirJourney getFlightDetailsFromAirportPairing(String airportPair)
{
Journey matchJourney = new AirJourney(0, null, null);
for(AirJourney journey : database)
{
String journeyPair = journey.getOriginAirport() + journey.getDestinationAirport();
if(airportPair.equals(journeyPair))
{
if(matchJourney.getMileage() == 0)
{
matchJourney = journey;
}
else if(journey.getMileage() < matchJourney.getMileage()
{
matchJourney = journey;
}
}
}
return matchJourney;
}
Loop through every journey and add a check for the mileage.
use below method using java 8 streams and it might help you :
public static String getFlightDetailsFromAirportPairing(String airportPair) {
List<String> database = Arrays.asList("DE400", "DE300"); // you can get it from your database
String journeyPair = "DE"; // you can get it from your database
int minimumMiles = database.stream().map(value -> Integer.valueOf(value.split("(?<=\\D)(?=\\d)")[1])).collect(Collectors.toList()).stream().reduce((x, y) -> x.compareTo(y) <= 0 ? x : y).get();
if (airportPair.equals(journeyPair) ) {
return journeyPair + minimumMiles;
} else {
return null;
}
}
For your minimumMiles from journey you can use :
int minimumMiles = database.stream().map(journey -> journey.getMiles()).collect(Collectors.toList()).stream().reduce((x, y) -> x.compareTo(y) <= 0 ? x : y).get();
I am assuming that getMiles() is returning integer , if it is not then you have to use Integer.valueOf(journey.getMiles())
It will get minimum miles for a airportPair and then will give the result.
Please do let me know if that worked for you or not.

need to store value after passing to method for latter check

I am passing few values to mail method for sending the details like below
private static String getTeam(String Team, List<String> prioritys1, String number,String description
) {
StringBuilder builder1 = new StringBuilder();
for (String v : prioritys1) {
if ( v == "1") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
else
if ( v == "3") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
}
return builder1.toString();
}
I tried to store in arrays but it didnt worked.
I after pass above parameters, i need to store the value of the number. i need to store the number so that next time while passing the parameters i need to check first whether the number is already passed or not if not then only i need to pass to mail.
can any one help on this
With this code very complicated understand what you are doing. But if you need check value that already been processed store it outside of the method. Create global class variable:
public class className {
private final List<String> ARRAY = new ArrayList<>(); // global variable
public void yourMethod(String value) {
if (!ARRAY.contains(value)) {
mail(value);
ARRAY.add(value);
}
}
}
I dont know your case and I can not get better example.
You need to store the value in a "class level" variable. Whether the variable type needs to be static or instance will depend on your implementation of the method.
If you can post a sample code, we can help further.
You need to compare with 2 equals and not 1
Instead of
if( Team = A )
you need this way
if( Team == A )
Using Team = A, your saying that every time your code reaches that line it will equal Team to A.

Increment a static variable in object before returning that object

I have some code that creates Objects called Weights. Now there are subclasses of these Weights called - WeightSmall, WeightMedium, and WeightLarge - each with their own static variable called onScreen. This variable should increment when one of either WeightSmall, WeightMedium or WeightLarge is added, however these get return on the call of the create method rather than being added to an array. I have an array of Weight objects - is there a way to access what subclass type an element is in the array of the parent class?
Here is the code for creating weights:
public Weight createWeight() {
decider = Math.random() * 1;
// creates rocks randomly with the lowest chance for l, and the highest chance for m
if (decider <= 0.33) {
// small weight
return new WeightSmall(BitmapFactory.decodeResource(getResources(), R.drawable.weight_s), new Random().nextInt(screenWidth), -10);
} else if (decider <= 0.5 && decider > 0.33) {
// large weight
return new WeightLarge(BitmapFactory.decodeResource(getResources(), R.drawable.weight_l), new Random().nextInt(screenWidth), -10);
} else {
// medium weight
return new WeightMedium(BitmapFactory.decodeResource(getResources(), R.drawable.weight_m), new Random().nextInt(screenWidth), -10);
}
}
What needs to happen is for WeightSmall lets say, it needs to check WeightSmalls onScreen variable to see if it's smaller than, let's say 3. if it is return the weight. However I can't think of a way to access WeightSmall's onScreen variable as it needs to be created more than once and I tried implement them into an ArrayList but it causes complications in the update method. Here is the rest of the code (that matters) for the class:
public void render(Canvas canvas) {
if (canvas != null) {
canvas.drawColor(Color.WHITE);
player.draw(canvas);
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.draw(canvas);
}
}
}
// updates the weight's position on the screen and checks collision with the player
public void update() {
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.update();
if (weight.getBounds().intersect(player.getBounds())) {
player.setTouched(false);
Intent gameOverIntent = new Intent(this.getContext(), GameOverActivity.class);
this.getContext().startActivity(gameOverIntent);
((Activity) getContext()).finish();
}
}
}
// count down timer spawning weights in every tick
public void timer() {
if (start == true) {
if (weightSpawnTimer != null) {
weightSpawnTimer.cancel();
weightSpawnTimer = null;
}
weightSpawnTimer = new CountDownTimer(30000, 800) {
public void onTick(long millisUntilFinished) {
weights.add(createWeight());
}
public void onFinish() {
weightSpawnTimer.start();
}
}.start();
}
}
Edit for clarity: What I need to happen, is in the onTick method, check if the subclass of weight's onScreen variable is <= 3, if it is, create a new weight, if it isn't do nothing. Once the weight is then offscreen, decrement this variable so new weights of that subclass can then be created.
What about
class WeightSmall {
public WeightSmall(...) {
// increment static
}
}
Let each class be responsible to increment it's own number in case an instance is created.
Modifying a static variable from an instance is usually considered bad practice. The few legit use-cases are typically some sort of instance counting. At least when you don't count down.
Counting down is where the trouble starts because Objects do have a defined start but their end is not guaranteed. You can count down in finalize - i.e. when the garbage collector has found your instance - but that's not guaranteed to happen soon or at all. Using that to find out how many instances are on screen would correlate to the actual number but could be completely wrong.
So in a case when you want to know how many objects you show on screen you must actively count that number down once the place responsible for showing the objects let's go of one.
And since that is already a responsibility for the class that wants to know how many objects are on screen, it should as well keep track of the numbers in a local variable of it's own.
By using a static property you limit yourself to have just 1 screen. If you let the other place count the number you don't limit yourself.
Static variable initialized at 0, then on the constructor your make it +1

ArrayList does not print removed objects

I have a class called Polynomial with an ArrayList made up of term objects, there is an external file that is read by a Scanner object in my test class. The Scanner reads the line for 4 different key words and acts accordingly. ex. INSERT 3 2. Would call my insert method and print out 3x^2. Now I have a delete method with two parameters. When I call the method in the test class nothing happens, the same thing gets printed and nothing has been removed. Am I missing something or doing it wrong all together? Any help is greatly appreciated.
public void delete (int coeff, int expo)
{
for (int i = 0; i<terms.size(); i++)
{
Term current = terms.get(i);
terms.remove(current.getCoeff());
terms.remove(current.getExpo());
}
}
I also have a Term class that creates a term object, and has two methods to get the coefficient and exponent.
Here is a snippet of my test class:
public static void main(String[] args) throws IOException
{
// TODO code application logic here
Polynomial polyList = new Polynomial();
Scanner inFile = new Scanner(new File("operations2.txt"));
while(inFile.hasNext())
{
Scanner inLine = new Scanner(inFile.nextLine());
String insert = inLine.next();
if(insert.equals("INSERT"))
{
int coeff = inLine.nextInt();
int expo = inLine.nextInt();
polyList.insert(coeff, expo);
}
if(insert.equals("DELETE"))
{
int coeff = inLine.nextInt();
int expo = inLine.nextInt();
polyList.delete(coeff, expo);
}
}
System.out.println(polyList.toString());
}
}
Edit: this is a sample of the .txt file that is being read by the scanner class:
INSERT 3 2
INSERT 4 4
INSERT 1 6
INSERT 2 0
INSERT 5 2
INSERT 6 3
PRODUCT
DELETE 3 2
INSERT 2 7
DELETE 4 4
INSERT 4 10
Edit: Here is the Term class:
class Term
{
//instance vars
private int coefficient;
private int exponent;
public Term(int coeff, int expo)
{
coefficient = coeff;
exponent = expo;
}
public int getCoeff()
{
return coefficient;
}
public int getExpo()
{
return exponent;
}
#Override
public int hashCode()
{
return coefficient + exponent;
}
#Override
public boolean equals(Object o)
{
if (!(o instanceof Term))
{
return false;
}
Term t = (Term)o;
return coefficient == t.coefficient && exponent == t.exponent;
}
}
If your delete() method is trying to delete the Twrm with the specified coefficients, I recommend the following:
Override the equals() method to return true if the argument is a Term with the same coefficient and exponential
Override the hashCode() method to return a hash based on the same two values
Since the equals() method should make a value comparison, such an implementation is quite reasonable.
Once you've done that, your delete method becomes one line:
terms.remove(new Term(coeff, expo));
The implementation should look like this:
// in the Term class
#Override
public boolean equals(Object o) {
if (!(o instanceof Term)
return false;
Term t = (Term)o;
return coeff == t.coeff && expo == t.expo;
}
Although overriding the hashCode method is not strictly required to make your code work, it is good practice, so here's an example impl:
#Override
public int hashCode() {
return 31 * coeff + expo;
}
You're not trying to remove the Term from the terms list, but rather trying to remove the coefficient and exponent.
for (int i = 0; i<terms.size(); i++)
{
Term current = terms.get(i); // Your list contains Term objects
terms.remove(current.getCoeff()); // but you are try to removing a coefficient
terms.remove(current.getExpo()); // and an exponent
}
Just a general note also that removing this way will not work because i will be getting larger and your list will be getting smaller. So by the time you get to remove the last term for example (where i = terms.size() - 1), there will only be 1 item left in the list. If you're trying to remove all of the items, consider the list's clear method.
Why does your delete method take the arguments coeff and expo ....
...it does not do anything with them.
In fact, the delete method looks very suspicious. You will need to give more detail on what the terms array looks like, right now it makes no sense.
rolfl

java retain information in recursive function

Is it possible to retain information via a helper function with java, without using static variables.
For example,
public void foo(){
int v = 0;
fooHelper(2);
}
public void fooHelper(int depth){
v++;
fooHelper(depth-1)
}
Namely I want to update variable v without loosing the information for each recursive case, without having to access a variable outside the function.
Forget about all the answers that tell you to declare attributes, or to update mutable objects in each recursive call. In a true functional, recursive style you "retain" information by passing it as parameters and/or return types.
Let me illustrate with a simple example, let's say that you want to recursively calculate the sum of the elements in an int[]. Here, the state (the information that needs to be retained between recursive calls) is the current index in the array and the sum so far. Here's how to do it:
public int sum(int[] array) {
return sum(array, 0, 0);
}
private int sum(int[] array, int idx, int acc) {
if (idx == array.length)
return acc;
return sum(array, idx+1, acc+array[idx]);
}
Call it like this:
int[] array = {1, 2, 3};
System.out.println(sum(array));
As you can see, there's no need to declare (static or instance) attributes, and no need to pass and modify mutable objects (lists, maps) - I'm not even using local variables, because all the required information needed to solve the problem is present as method parameters.
In the code in your question the v variable is supposed to do what the acc parameter is doing in my answer, namely: modifying an accumulated value each time the recursion is called. In the end, you just need to return the accumulated value from the helper function (which must not have a void return type) and that's how you'll get the value in foo().
A variable declared in a scope (for example method) is accessible only in this scope (e.g. not in another method).
If the information is relevant for the method only, keep the variable in the method. If the information is relevant for the whole object / class state, keep it a class member (static/non static).
For example:
public void someRecursiveMethod(int num) {
while (num < 10) {
num++;
someRecursiveMethod(num);
System.out.println("Current num = " + num);
}
}
You can create a new class (yuck), or pass the variable as a parameter and return it in fooHelper.
Why not make it an instance variable(not necessarily static)...??
public class Recursive {
int v = 0;
public void foo(){
fooHelper(2);
System.out.println(v);
}
public void fooHelper(int depth){
v++;
if(depth-1!=0)//Added this because I was getting an StackOverflowError
fooHelper(depth-1);
}
public static void main(String[] args) {
Recursive r = new Recursive();
r.foo();
}
}
You could return a list or a similar data structure:
public List<Integer> fooHelper( int v, int depth ){
if( depth == 0 ) return new ArrayList();
v++;
List<Integer> result = fooHelper( v, depth-1 );
result.add( new Integer(v) );
return result;
}
Because the variable v is of primitive type, changes made to it will not be visible outside the function scope. You could declare the variable v inside a class, say State and pass the state object into the recursive function to get the required effect.
public void foo(){
State state = new State();
fooHelper(state, 2);
}
public void fooHelper(State state, int depth){
state.v++;
fooHelper(state, depth-1);
}
class State {
int v;
}
Hope it helps.
You can pass an object to store the update for each recursive call. Something like the one below.
public static void fooHelper(int depth, HashMap map){
map.put(depth, "Call " + depth);
if (depth > 0)
{
fooHelper(depth-1, map);
}
return;
}
I think this is called memoization. It looks like
class Fibonacci
{
public Map < Integer , Integer > memorized = new HashMap < > ( ) ;
public int fib ( int n )
{
if ( memoized . containsKey ( n ) )
{
return memoized . get ( n ) ;
}
else
{
int fib = // calculate recursively
memoized . put ( n , fib ) ;
return fib ;
}
}
}
You should be able to get decent (not optimal) performance out of this algorithm. The primary reason that the recursive fibonacci algorithm has horrible performance is b/c it is repeatedly calculating the same values. With recursion+memoization it never calculates any value more than once.
Thanks to #Aristide for pointing out the subtle difference between memorization and memoization.

Categories