Comparing elements of arrays in java - java

I have two arrays. In one, I have stored objects. In the second, there are just values. I need to compare an attribute of the stored objects with the element of the second array.
In the code I have posted below, I need to compare the 5th value of the objects with the elements of the second array. And come up with a method if the value is greater. Any suggestions?
ParkedCar a1 = new ParkedCar ("Toyota", "Camry", "Blue", 672, 85);
ParkedCar a2 = new ParkedCar ("Mitsubishi", "Pajero", "White", 988, 40);
ParkedCar a3 = new ParkedCar ("Ferrari", "GTC4", "Yellow", 1, 220);
ParkedCar a4 = new ParkedCar ("Perodua", "Myvi", "White", 3714, 260);
ParkedCar a5 = new ParkedCar ("Toyota", "Prius", "Black", 1472, 367);
ParkedCar parkingLot[] = {a1, a2, a3, a4, a5};
ParkingMeter aa = new ParkingMeter ();
aa.setMinutesPurchased(120);
ParkingMeter bb = new ParkingMeter ();
bb.setMinutesPurchased(60);
ParkingMeter cc = new ParkingMeter ();
cc.setMinutesPurchased(120);
ParkingMeter dd = new ParkingMeter ();
dd.setMinutesPurchased(150);
ParkingMeter ee = new ParkingMeter ();
ee.setMinutesPurchased(60);
ParkingMeter meters[] = {aa, bb, cc, dd, ee};

If I understand, you are assuming that parkingLot and meters have the same length, and that meters[i].minutesPurchased contains a value that refers to parkingLot[i] .
I assume you have some getter method in ParkedCar and ParkingMeter classes that get what you need.
If so, the only viable solution is some kind of for-loop:
for (int i = 0; i < parkingLot.length; ++i)
if (parkingLot[i].fifthField > meters[i].minutesPurchased)
callSomeMethod();
Personally, I think it's a bad idea to keep the link between the two classes in two different arrays. Probably you could add some method ParkedCar.getParkingMeter() to have the correct answer without the need of a for-loop.

Your question is a bit vague, so I am not sure if this is exactly what you are going for; but here's my take on it.
ParkedCar is just an object right? So each of those values you pass into it when creating {a1, a2... a5} are just attributes of a ParkedCar-just like ParkingMeter. With those attributes of each object, you can make "getters" for comparing the two.
E.G.
In your ParkedCar class:
public class ParkedCar{
private double attributeFive;
ParkedCar(){}
ParkedCar(String Make, String Model, String Color, double valueFour, double valueFive){
//logic for setting values
attributeFive = valueFive;
}
public double getValueFive(){
return attributeFive;
}
}
Now there are things missing in this code such as setters, but this should give you a picture. You can do the same thing in your ParkingMeter class.
All you need to do now is to compare the two values (say in the same method you creating the objects).
if(a1.getValueFive < aa.getMinutesPurchesed){
//do something
}
It seems like you had most of the logic already there, but was just missing a simple comparison. You might try and watch some YouTube tutorials to get the basic principles down for Java-I know that's what helped me start.

So you want to //Do Something if the ParkedCar's 5th value is higher than the minutes purchased.
You can write a function to do this.
Including checks for if both arrays are same size.
Your function is simply
for(int i = 0, i < parkingLot.getLength(), i++) {
if(parkingLot[i].getFifthValue() > meters[i].getMinutesPurchased()))
//DoSomething
}
However, ParkedMeter is quite a simple class. Why not add that as an attribute to ParkedCar. In that case, this meter value check is simply a oneliner boolean function in your ParkedCar Class return fifthValue > minutesPurchased;

Actually to acceess the elements' parameter in the second array,you have to
use getters to get the value of them and compare with the first array's fifth elements value.
In your ParkingMeter put a getter method like this:
public double getMinutesPurchased(){
return this.MinutesPurchased;
}

Related

How do ArrayList, static, and this work in Java?

I was going through the article Java Sorting: Comparator vs Comparable Tutorial, and have some questions about it.
List<Employee> col = new ArrayList<Employee>();
col.add(new Employee(5, "Frank", 28));
col.add(new Employee(1, "Jorge", 19));
col.add(new Employee(6, "Bill", 34));
col.add(new Employee(3, "Michel", 10));
col.add(new Employee(7, "Simpson", 8));
col.add(new Employee(4, "Clerk", 16));
col.add(new Employee(8, "Lee", 40));
col.add(new Employee(2, "Mark", 30));
return col;
This is an ArrayList of Employee objects. How many items can I add in this employee object? Can I do something like this?
col.add(new Employee(5, "Frank", 28, "asas", "asas"));
This is basically an array of Objects like Array[0] contains all these. And I am actually trying to access these array of Objects via ArrayList.
Why is the printList made static? Can I also have other types here?
private static void printList(List<Employee> list) {
System.out.println("EmpId\tName\tAge");
for (Employee e: list) {
System.out.println(e.getEmpId() + "\t" + e.getName() + "\t" + e.getAge());
}
}
While comparing, what does this represent and o represent?
public int compareTo(Employee o) {
return this.empId - o.empId;
}
What does this mean here?
how many items can i add?
You can add items to the list until the Java VM runs out of memory. There is no artificial limit.
can i do something like this?
col.add(new Employee(5, "Frank", 28, "asas", "asas"))
No, because the Employee has no constructor which takes these arguments. But you can
col.add(new Employee(5, "Frank", 28));
This gives you two very similar but not identical instances in the list (they aren't identical because they are at different places in memory; they are similar because all fields have the same value).
Why does the printList made static?
So it can be called from the static method main() without creating an instance of TestEmployeeSort
what does this represent and o represent?
The sort algorithm will select two items in the list and call compareTo() on one with the other as argument. The former will be this, the latter will be in o.
This way, the sort algorithm doesn't need to know much about the objects it compares.
The advantage is that you can easily make objects comparable. The drawback is that the list must not contain null pointers or non-Employee instances.
If that doesn't work for you, you can create a Comparator which also has a compareTo method but it takes two arguments.
John,
col.add accepts only one Bject. So, you creates one Employee object with a new operation and adds it a list. So, you cannot use this - new Employee(5, "Frank", 28, "asas", "asas"), because Employee object doesn't have such constructor. Evene if it has such constructor it creates only one Employee object.
printLine is static, because you need to create TestEmployeeSortobject first, to use non-static method. But it doesn't have any sense (to create non-static object) because printLine doesn't use internal state of TestEmployeeSortobject, so, it can be and must be static in this case.
compareTo defines whi is bigger than other one. See the API:
Returns:
a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
So, in that case author decides that Employee is greater if Id is greater. You can change that method to use any other field to define sorting order.
this references the current instance of your object , o is the Employee parameter of the compareTo function. You can't sort a list without knowing how to compare the Objects in the List, in this case you compare the employee ids.
Also it would be more elegant to do a
System.out.println(e.toString());
and overriding toString method for Employee, instead of calling getters for each field.
You can add more "items" to the Employee object if you modify it's class variables and constructor:
public class Employee {
private int empId;
private String name;
private int age;
// add new var
private Object x;
public Employee(int empId, String name, int age) {
// set values on attributes
}
// add new construct
public Employee(int empId, String name, int age, Object x) {
//set the other attributes
// this.x represents the current instance's x property, and x represents the parameter from the construct
this.x = x;
}
// getters & setters
}
To get objects I would recomment myList.get(index)...
You can add the new variable in the printList method, of course.
see the answer from #Sleeperson
First question: No you can't unless there is another constructor that is
Employee (int, String, int, String, String)
Second question: I'm unsure what you are asking...I'm sure someone else can help though.
Third question: "this" represents the Employee calling the method compareTo and "o" represents the employee that is passed as an argument. Most compareTo methods return 0 if the objects are equal and in this case, anything else if the objects aren't. So this method compares employee ids. If it is the same Employee, this.empId - o.empId will return 0
Can i do something like this?
Yes.
col.add(new Employee(5, "Frank", 28, "asas", "asas"))
is same as
Employee e = new Employee(5, "Frank", 28, "asas", "asas");
col.add(e);
How many items can i add in this employee object
You meant the list right? There is no practical limit.
Why does the printList made static?
This printList method is a utility method. This does not have nothing to do with the data of the class, and does some, well, utilities, and does not have to be present in every instance of the method. Methods doing some formatting, logging and such stuff are generally static.
While comparing... what does this represent and o represent.
In compareTo, this is the current object on which compareTo is called, and o is the object passed on to it.
So when you say e1.compareTo(e2), e1 is this and e2 is o.

how to sort same string array into a new string and count it.

I'm doing a java project and I want sort same string array then count how many each car brand have. I am stuck passing an array into int variable. need suggestions. thanks.
public class SortCars {
public static void main(String[] args) {
String[] cars = {"honda", "toyota", "honda", "toyota"};
String[] honda = new String[5];
String[] toyota = new String[5];
int numOfHonda;
int numOfToyota;
for (int i = 0; i < cars.length; i++) {
if (cars[i].equals("numOfHonda")) { //
honda[i] = cars[i];
honda[i] = numOfHonda; // stuck here
numOfHonda++;
}
}
}
}
You seem to have confusion with String and int values. Since you say you are in the beginning week of your programming and From what I understand from the question. This is what you are trying to do:-
public static void main(String[] args) {
String[] cars = {"honda", "toyota", "honda", "toyota"};
String[] honda = new String[5];
String[] toyota = new String[5];
int numOfHonda = 0; // you need to initialize these int variables
int numOfToyota = 0;
for (int i = 0; i < cars.length; i++) {
if (cars[i].equals("honda")) { // if cars has element honda
honda[i] = cars[i]; // putting cars element in honda array
numOfHonda++; //incrementing value of numOfHonda by 1
}
else if(cars[i].equals("toyota")){
toyota[i] = cars[i];
numofToyota++;
}
}
Now Printing numOfHonda and numofToyota will give you the number of Hondas and Toyotas respectively.
Apart from my answer, I would like to address some errors that I found in your code.
int numOfHonda; //initilize your variable. Otherwise you will get compilation error! make it = 0 in this case.
int numOfToyota; // same here, initialize to 0.
if (cars[i].equals("numOfHonda"))
Here you are trying to compare cars[i] element to a string "numOfHonda".If you look at your code there is no such String declared as "numofHonda". There is one thing which is an int type variable
equals() method does not compare int type with String. It always compares String with String. And the fact that you have put your int variable numofHonda inside " " does not make it the same thing! "numofHonda" and numHonda are different things!
honda[i] = numOfHonda;
You were stuck here because you know what you are doing here?
you are trying to put int type variable(numOfHonda is of int type remember?)
inside a String array. This is not possible. It is a type mismatch. The basic definition of Any type of Array is it holds the same type of elements. So honda[] can not store an int type value.
Hope you have a better view now. Keep Learning.
It will be quite simple if you're allowed to use Java 8. Here's the code.
String[] cars = {"honda", "toyota", "honda", "toyota"};
Map<String, Long> data = Arrays.stream(cars)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(data); // => {toyota=2, honda=2}
Use TreeMap- Simple and precise solution
String[] cars = {"honda", "toyota", "honda", "toyota"};
TreeMap<String, Integer> map = new TreeMap<>();
for(String s: cars){
int count = map.containsKey(s) ? map.get(s) : 0;
map.put(s, count+1);
}
System.out.println(map);
output
{honda=2, toyota=2}
So you want to go over an array of cars and sort it into different array depending on there manufacturer? If so, here's my approach:
import java.util.ArrayList;
String[] cars = {"honda", "toyota", "honda", "toyota"};
ArrayList<String> honda = new ArrayList<String>();
ArrayList<String> toyota = new ArrayList<String>();
for (int i = 0; i < cars.length; i++) {
switch(cars[i]) {
case "honda":
honda.add(cars[i]);
break;
case "toyota":
toyota(cars[i]);
break;
}
}
I would suggest to use ArrayList (java.util.ArrayList) much more versatile. Furthermore I would use a switch-statement. And counting the amount of each manufacturer seems unnecessary to me, just check via honda.length.
EDIT: in depth explanation
ArrayList
Okay, so here it is step by step. My Code does not really differs too much from yours. I change the manufacturer array to by ArrayList which is a 'CustomDatatype'. Under the hood it uses an array but it provides us with a few functionalities which make it easier to interact with this array (e.g. the .add() method to easily add an element to the ArrayList). To initialize an ArrayList we need to call the new-keyword since it a class not a basic datatype. We also need to tell the Array what datatype the element inside it have, this is what we to with the angle brackets (ArrayList<ELEMENT_DATATYPE>())
switch()
The switch statement take whatever you 'give' it as the parameter in parentheses and tries to match it with the cases defined in the switch function. If a match is found it runs whatever code is defined by the case. Switch statements also have the ability to have fall through which keeps checking for matches even when the first is found, this can be useful but for now the prevent this with using the break-statement. A proper switch-case also has a default case which will run when no match is found, but this is also left out here due to complexity. (#otherDevs: sue me, I'm trying to explain things)
Conclusion
I tried to show a way using your approach and slightly changing it but in general it is the same, of course there a many ways to solve this stuff like Map and so on. But as you're just starting I recommend going with the basics. AND you really should get familiar with the Java-Docs since having the ability to read and use docs it pure gold as a developer.

Each object stored in Map returns values stored in last object

I checked for a few solutions on this but they all seem to say the issue is when people use the "static" word or aren't using the class name when creating the HashMap. I am trying to create a map that contains a person's name (key) and their test scores (value). I am trying to pass an object in for the value do this:
HashMap<String, Scores> map = new HashMap<String, Scores>();
List<Integer> scores = new ArrayList<Integer>();
scores.add(55);
scores.add(66);
scores.add(77);
map.put("foo", new Scores(scores));
scores.clear();
scores.add(70);
scores.add(80);
scores.add(90);
map.put("bar", new Scores(scores));
System.out.println(map.get("foo").getScores());
System.out.println(map.get("bar").getScores());
System.out.println(map.get("foo").getAverage());
and for my Scores Class I have the following:
List<Integer> scores = new ArrayList<Integer>();
private int sum = 0;
public Scores(List<Integer> s){
this.scores = s;
}
public double getAverage(){
int count = 0;
for (int x: this.scores){
this.sum += x;
count++;
}
return this.sum / count;
}
public List<Integer> getScores(){
return this.scores;
}
When I run my code I get the following output:
[70, 80, 90]
[70, 80, 90]
80.0
I am not using "static" to store my scores and I use clear() afterwards to keep old values from repeating. I am also using the class name when creating my HashMap<> variable.
Can anyone tell me why both 'map.get("foo")' and 'map.get("bar")' return the same values and how I might fix this? Can they also provide a working example? Thanks!
new Scores(scores) doesn't create a copy of the List instance passed to it. It stores a reference to that List.
Therefore both Scores instances you put as values in the Map refer to the same List.
Instead of
scores.clear();
you should create a new List :
scores = new ArrayList<Integer>();
in order for the two Scores instances to refer to different Lists.
Primitives (byte, short, int, long, float, double, boolean, char, etc) and reference types (any instantiable class as well as arrays. String, Scanner, Random, Die, int[], String[] , etc.) have different behaviors.
You will need to actually instantiate a new ArrayList - like this:
scores = new ArrayList<Integer>();
to create a new list. In your code, you are just passing a reference to the same list.

Array to store objects of two different classes?

I am a beginner in java and programming in general.Basically, I am wondering whether if it is possible to store objects of different classes in the same array. For example, instead of create 2 seperate arrays like this:
//AssembledPart is subclass of Part
Part[] part = new Part[4];
part[0] = new Part("p101", "Crank", 218, 12.20);
part[1] = new Part("p102", "Pedal", 320, 14.30);
part[2] = new Part("p103", "Handlebar", 120, 35.50);
part[3] = new Part("p104", "Stem", 90, 20.00);
AssembledPart[] asPart = new AssembledPart[2];
asPart[0] = new AssembledPart("p183", "Crank-Pedal", 80, 3.50, part[0], part[1]);
asPart[1] = new AssembledPart("p184", "Handlebar-Stem", 30, 1.50, part[2], part[3]);
Is there any other way to combine them in to just one array.If there is a way, how can I do it.
If AssembledPart is a subclass of Part (as you indicated in the comments), then what you're asking is trivial. Subclasses can always be assigned to their parent classes, so all you need to do is:
Part[] part = new Part[6];
part[0] = new Part("p101", "Crank", 218, 12.20);
part[1] = new Part("p102", "Pedal", 320, 14.30);
part[2] = new Part("p103", "Handlebar", 120, 35.50);
part[3] = new Part("p104", "Stem", 90, 20.00);
part[4] = new AssembledPart("p183", "Crank-Pedal", 80, 3.50, part[0], part[1]);
part[5] = new AssembledPart("p184", "Handlebar-Stem", 30, 1.50, part[2], part[3]);
From the official documentation Java Arrays:
An array is a container object that holds a fixed number of values of
a single type...
The short answer is that you cannot use different classes.
However, the trick here is that you can use object orientation so that an array is created for a more generic class which allows for subclasses to be set in the array.
You mentioned that AssembledPart is a subclass of Part, and that means you are allowed to set a AssembledPart object into a Part array. Like this:
Part[] yourArray = new Part[2];
yourArray[0] = new Part();
yourArray[1] = new AssembledPart();
This very same concept will work not only when using collections but in many other object usage, in virtually all object oriented languages.
I suggest you to read more in Object-Oriented Programming Concepts, will clear your mind in some of this concepts =).
No, you cannot have different objects in the same array. When you create an object array, you specify a certain object to be put into that array. You'll have to create different object arrays for different classes.
You can create an interface IPart and implement that in both Part and AssembledPart. that way you can create an array of that interface and use that array to store both Part and AssembledPart object there.
interface IPart {
}
class Part implements IPart {
}
class AssembledPart implements IPart {
}
// in code you can do following...
IPart[] parts = new IPart[2];
parts[0] = new Part(...);
parts[1] = new AssembledPart(...);
you can also do it by extending the AssembledPart
class Part {
}
class AssembledPart extends Part{
}
// in code..
Part[] parts = new Part[2];
parts[0] = new Part(...);
parts[1] = new AssembledPart(...);
another way you can do it by using array of Object
Object[] parts = new Object[2];
parts[0] = new Part(...);
parts[1] = new AssembledPart(...);
but you need to understand why you want to merge two array and how you want to merge it.
fyi, at some point you may need to check what kind of object you have in the array. you can do it by using.
if(parts[0] instance of AssembledPart) {
// do something.
}

Two-dimensional array of Lists

I'm in the need of a two dimensional matrix of list, e.g. ArrayList, and I'm wondering what is most preferable in this case. It only needs to be 4x4 in size.
Should I use something like
ArrayList[][] foo = new ArrayList[4][4];
or
ArrayList<SomeClass>[][] foo = new ArrayList[4][4];
and initialize every element with the proper type in a for loop or
ArrayList<ArrayList<ArrayList<SomeClass>>> foo = ArrayList<ArrayList<ArrayList<SomeClass>>>();
The first method generates warnings like it should be parametrized and if I add use the second I get unchecked conversion warnings. But if I loop over the elements and initialize them there should not be any problem even if I still get the warning? The last method does not generate any warnings and probably works fine but it feels kinda messy.
EDIT: Got some nice answers to my question even if it was a bit unclear. But it was basically how to make a table of Lists. Creating a custom class to handle rows/columns it made it a a lot easier.
Fix the first method as following:
List[][] foo = new ArrayList[4][4];
The second method is not what you need. You are trying to create 4 dimensional array instead of 2 dimensional array 4*4 elements.
Additionally I'd like to give you a tip: never use concrete class in the left of assignment, i.e. ArrayList list = .... Use List list = ...
And avoid using too complicated data structures. 2 dimensional array of lists is too complicated. Create your custom class that encapsulates some functionality and then create collection / array (better 1 dimensional) of objects of your class.
Here's example for 2x2 matrix with explicit initialization.
List<MyClass>[][] matr = new List<MyClass>[][] {
new List<MyClass&gt { new ArrayList<MyClass>(), new ArrayList<MyClass>() },
new List<MyClass&gt { new ArrayList<MyClass>(), new ArrayList<MyClass>() }
}
Like Alex already said, having a 2 dimensional array of lists is quite complicated and easy to get wrong or be used in a wron way.
Since your array should represent a table you might want to create classes for the rows or columns, depending on what is more important.
Alternatively, you could create a class for each cell in the table and manage a 2D array of cells, if you know exactly what number of cells you'd have:
class Cell {
private List<SomeClass> content = new ArrayList<SomeClass>();
...
}
Cell[][] matrix = new Cell[4][4]; //don't forget to initialize each cell
public static class Grid<T> {
public interface TFactory<T> {
T create();
}
private T[] data;
private int d1;
private int d2;
public Grid(int d1,
int d2,
Class<T> clazz,
TFactory<T> fac) {
this.d1 = d1;
this.d2 = d2;
data = (T[]) Array.newInstance(clazz, d1 * d2);
for (int i = 0; i < data.length; i++) {
data[i] = fac.create();
}
}
public T get(int c1,
int c2) {
return data[c1 * d2 + c2];
}
}
public static class ArrayListFactory<X> implements Grid.TFactory<ArrayList<X>> {
public ArrayList<X> create() {
return new ArrayList();
}
}
public static void main(String[] args) throws RTXException, ParseException {
// cannot use new new ArrayList<String>[4][4];, because of generic array creation error
List<String>[][] a2d = new ArrayList[4][4];
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
a2d[i][j] = new ArrayList<String>();
}
}
Grid g = new Grid(4, 4, ArrayList.class, new ArrayListFactory<String>());
}
Here are two approaches. First is what you asked for, second is encapsulated version (with 2d array transformed into 1d array for easier internal manipulation).
As was said before, you should declare variables as interfaces as much as possible (but not more).
That mean, if all you want to say is, its a List and does not expect anyone to behave differently based on concrete implementation, just use List, not ArrayList as variable type.
But if you use eg. LinkedSet it can be good idea to use LinkedSet as variable type (and as return value of functions), if you want to "promise" that it lists all elements quicly and in insertion order. If you use Set, user of it should not depend on any particular order of iteration.
btw. beware of explicit initialization. It is nice syntax, but it creates anonymous inner class and it can lead to inintended retention of parent class. But if you know what you are doing and that it is not possible to happen (no outside reference) there is nothing wrong with using it.

Resources