searching custom objects in arrays and arraylists in java - java

I have written an employee class which has a display method and the constructor.
public class employee {
public int empid;
public String name;
public employee(int id, String name){
empid = id;
this.name = name;
}
public void display (){
System.out.println("Employee id: " +empid +"\nEmployee name: "+name);
}
}
I then created three objects of employee and stored them in an array in the main class. I created an if block which will check user guess and print the employee details if he exists or will throw an exception if the data is not present. The if block was enclosed in an enhanced for loop which loops through the array.
public static void main(String[] args) {
// TODO code application logic here
employee priya = new employee (001, "Priya");
employee tamizh = new employee (002, "Tamizh");
employee hari = new employee (003, "hari");
employee[] list = new employee[3];
list[0] = priya;
list[1] = tamizh;
list[2] = hari;
int userGuess = 002;
for (employee l : list){
if (userGuess == l.empid)
{
l.display();
break;
}
else
{
throw new InputMismatchException ("employee doesnot exist");
}
}
}
}
The trouble is that the program throws the exception even if the guess is correct. I tried the int variable empid and then the String variable name, but both the == and .equals didn't work. I searched stackoverflow and the solution suggested was to override the hashcode and equals method in the employee class. I did that.
public class employee {
public int empid;
public String name;
public employee(int id, String name){
empid = id;
this.name = name;
}
public void display (){
System.out.println("Employee id: " +empid +"\nEmployee name: "+name);
}
#Override
public int hashCode(){
final int prime = 31;
int result = 1;
result = prime * result + empid;
result = prime * result + name.hashCode();
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
employee other = (employee) obj;
if (this.empid != other.empid)
return false;
if (this.name.equals(other.name))
return false;
return true;
}
}
Now when I give the input as 001, the code works fine. But for any other input (including the existing empids 002 and 003), the exception is being thrown.
What had I done wrong in the overriding? Also I don't understand the code I had written to override the two methods. Can someone explain the logic and where I went wrong? Thanks.
Edit: Thanks guys. I have realized my mistake in the for loop and I have edited it. It works perfectly now.
int userGuess = 002;
boolean found = false;
for (employee l : list){
if (userGuess == l.empid)
{
l.display();
found = true;
break;
}
}
if(found == false){
try{
throw new InputMismatchException ("employee doesnot exist");
}
catch(InputMismatchException e){
System.out.println("Employee doesnot exist.");
}
}
Thanks a lot guys. Can someone explain what I have done in equals and hashcode methods? I copied the code from an answer and I couldn't find an explanation for it. Thanks again.

You iterate through your whole array starting at the first entry.
So if you compare the first entry with your user input (lets say its 002) the statement will be false. So it will throw an exception.
To solve this issue you would have to check if an entry has been found AFTER iterating through your array.
int userGuess = 002;
boolean userFound = false;
for (employee l : list)
{
if (userGuess == l.empid)
{
userFound = true;
l.display();
break;
}
}
if(!userFound)
{
throw new InputMismatchException ("employee doesnot exist");
}
To answer your second question:
i dont think you'll need the equals() and hashCode() method.
The equals checks if two objects are the same (see https://msdn.microsoft.com/de-de/library/bsc2ak47(v=vs.110).aspx)
the hashCode() method generates a "unique" value for an object (see https://msdn.microsoft.com/de-de/library/system.object.gethashcode(v=vs.110).aspx)

This should work for you:
boolean found = false;
for (employee l : list){
if (userGuess == l.empid) {
l.display();
found = true;
break;
}
}
if(!found){
throw new InputMismatchException ("employee doesnot exist");
}
Your existing code will not work because the first in the loop is always 001.

Related

How do I search an ArrayList of Objects

I am creating an ArrayList of Accounts (an object) and the Account constructor is
public Account(String name, int accNum, int balance)
{
myName = name;
myAccountNum = accNum;
myBalance = balance;
}
I want to know how to check the ArrayList to determine if a given accountNumber exists in it, and if it does, return true
private static ArrayList<Account> accounts = new ArrayList<Account>();
My initial thought was this, but I do not think that this works
if(accounts.contains(tempAccNum))
{
//executes code that I have
}
For the Java ArrayList, contains performs an object equality comparison. To use .contains, you would need to
Implement the .equals() method for the Account class, and have it check only the this.myAccountNum property against the account number of the input Account.
Create a dummy Account with the desired account number to pass into contains.
A better method would involve evaluating an iterator, and checking the account numbers at each step. Here I assume that myAccountNum is a public property of the Account class.
Iterator<E> it = Accounts.iterator();
while (it.hasNext()) {
Account acc = it.next();
if(acc.myAccountNum == tempAccNum)
return true;
}
For ArrayList specifically, using .get with an index is not too bad:
for(int index = 0; index < Accounts.size(); ++index) {
if(Accounts.get(index).myAccountNum == tempAccNum)
return true;
For other List types, using indices can be very poor.
Ways to iterate over a list in Java
I will suggest you to make it simple by just implementing an equals() method for account class.
#Override
public boolean equals(Object o){
if(o==null)return false;
if(o.getClass()!=this.getClass())return false;
Account demo = (Account)o;
if(!demo.myName.equals(this.myName))return false;
if(demo.myAccountNum != this.myAccountNum)return false ;
if(demo.myBalance = this.myBalance)return false ;
}
then use contains method
First add getter for accNum in Account model
Then try this
public boolean containsAcc(int accno) {
for(int i=0;i<accounts.size();i++) {
if(accounts!= null && accounts.get(i).getMyAccountNum()==acno) {
return true;
}
}
return false;
}
Here getMyAccountNum() is the getter declared in Account model(shown below)
Then check this
if(containsAcc(tempAccNum))
{
//your code
}
Your Account model should be like this
public class Account {
String myName;
int myAccountNum;
int myBalance;
public Account(String name, int accNum, int balance)
{
this.myName = name;
this.myAccountNum = accNum;
this.myBalance = balance;
}
public int getMyAccountNum() {
return myAccountNum;
}
}

Java Remove duplicated from multiple Array [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
i have a question on how to remove duplicate for multiple Array. Basically what i want to achieve is to compare from 4 Array and if the contain of Array are exactly the same then i want do not want to print out.
The example of contains for each as below shown:
ArrayStudentName ArrayAge ArrayGender ArrayCourse
A 9 Boy IT
B 10 Boy IT
B 9 Boy IT
A 9 Boy IT
A 9 Girl IT
Is that the only way to remove the duplicate with using 4 times of for loops or do i have to merge 4 arrays into 1 array and then use HashMap to remove duplicate before u print out the result.
The result i need is:
ArrayStudentName ArrayAge ArrayGender ArrayCourse
A 9 Boy IT
B 10 Boy IT
B 9 Boy IT
A 9 Girl IT
You should be brave and take the OOP route. Make a class called Student and fold all the values into that class. Then you just need to put them in a Set which, by definition, does not allow duplicates.
You do, however, have to implement equals and hashcode (or Comparable if you choose not to use a HashSet).
enum Gender {
Boy, Girl, Other;
}
enum Course {
IT, CS;
}
class Student {
final String name;
final int age;
final Gender gender;
Course course;
public Student(String name, int age, Gender gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
#Override
public String toString() {
return name + "\t" + age + "\t" + gender + "\t" + course + "\n";
}
#Override
public int hashCode() {
int hash = 5;
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Student other = (Student) obj;
if (!Objects.equals(this.name, other.name)) {
return false;
}
if (this.age != other.age) {
return false;
}
if (this.gender != other.gender) {
return false;
}
return true;
}
}
public void test() {
System.out.println("Hello");
List<Student> students = Arrays.asList(
new Student("A", 9, Gender.Boy),
new Student("B", 10, Gender.Boy),
new Student("B", 9, Gender.Boy),
new Student("A", 9, Gender.Boy),
new Student("A", 9, Gender.Girl)
);
// Fold it into a Set to eliminate duplicates.
Set all = new HashSet();
all.addAll(students);
// Pull back out into a List.
System.out.println("Students:\n" + all);
}
Create a Student Class.
public class Student {
private String name;
private int age;
private String gender;
private String course;
// Implement Getters and Setters here.
// Then Override the equals method like this:
#Override
public boolean equals(Object obj) {
Student student = (Student) obj;
if ( this.name.equals( student.getName() ) &&
this.age == student.getAge() &&
this.gender.equals( student.getGender() ) &&
this.course.equals( student.getCourse() )
) {
return true;
}
else {
return false;
}
}
}
Now you can create an array of Student objects and compare them using equlas method.
easy way: use a Set (to get unique entries), an keep order: LinkedHashSet
Then Read each line in a List< String >
and keep them in a LinkedHashSet< List< String> >
This gives something like that (you must loop and scan your datas of course !)
Set<List<String>> sls=new LinkedHashSet<List<String>>();
sls.add(Arrays.asList(new String[]{"A","9","Boy","IT"}));
sls.add(Arrays.asList(new String[]{"B","10","Boy","IT"}));
sls.add(Arrays.asList(new String[]{"B","9","Boy","IT"}));
sls.add(Arrays.asList(new String[]{"A","9","Boy","IT"}));
sls.add(Arrays.asList(new String[]{"A","9","Girl","IT"}));
System.out.println(sls);

Finding max/min value using Comparable

I have an object class
public class Film implements Comparable<Film>
I'm using Eclipse and would like to know why Film is underlined in red with the error saying:
The type Film must implement the inherited abstract method Comparable<Film>.compareTo<Film>
And now to my main question:
How would I get the max/min user submitted film length and title?
My object class Film has getter and setter methods for the Title of the film and the Length of the film and a toString method. Following this article (#3) I created two more methods in my object class:
public int max(Film maxLength){
int compareLength = ((Film) maxLength).getLength();
return this.length - compareLength;
}
public int min(Film minLength){
int compareLength = ((Film) minLength).getLength();
return compareLength - this.length;
}
Could I use these to find and print max/min values of the user submitted film lengths?
If so, how?
If not, what is the proper way of doing this?
The test class is as follows:
import java.util.Scanner;
public class test {
public static void main (String[] args){
Film[] f = new Film[3];
Scanner input = new Scanner(System.in);
for (int i=0;i<3;i++){
f[i] = new Film();
System.out.println("Enter Film Length:");
f[i].setLength(input.nextInt());
input.nextLine();
System.out.println("Enter Title:");
f[i].setTitle(input.nextLine());
}
input.close();
for (int i = 0; i < 3; i++) {
System.out.println(f[i].toString());
}
}
}
The Film class implements Comparable<Film>. What this means is that you must implement a method called compareTo() in class Film that will provide an ordering for objects of this class.
#Override
public int compareTo(Film that) {
// Order by film length
return Integer.compare(this.length, that.length);
}
If you only need to sort the objects by film length you can just use Arrays.sort():
Film[] films = new Film[3];
// put the objects into the array
Arrays.sort(films);
Then films[0] will contain the film with the shortest length, while the last element will be the film with the longest length.
If you need to compare by other fields, such as film title, you can create a custom comparator:
class FilmTitleComparator implements Comparator<Film> {
public int compare(Film a, Film b) {
return Integer.compare(a.getTitle().length(), b.getTitle().length());
}
}
And pass it to Arrays.sort()
FilmTitleComparator titleComparator = new FilmTitleComparator();
Arrays.sort(films, titleComparator);
Then films[0] will contain the film with the shortest title, while the last element will be the film with the longest title.
For simplicity, I stubbed your Film class to show a trivial example of how to implement Comparable
public class Film implements Comparable<Film> {
int maxLength;
int minLength;
String title;
public Film() {
this.maxLength = 0;
this.minLength = 0;
this.title = "";
}
// implement this method to accomplish comparison
public int compareTo(Film f) {
int result = 0; // the result to compute.
if ( this.equals(f) ) {
result = 0; // these objects are actually equal
}
// compare using meaningful data
else if ( f != null) {
// check to see if this film is greater than the specified film
if ( this.getMaxLength() > f.getMaxLength() ) {
// this film is comparatively greater, return > 0
result = 1;
}
else if ( this.getMaxLength() == f.getMaxLength() ) {
// these two films are comparatively equal
result = 0;
}
else {
// this film is comparatively less than the specified film
result = -1;
}
// similarly, you could also check min, but there's really no reason to do that unless your implementation calls for it.
}
else {
throw new IllegalArgumentException("null Film object not allowed here...");
}
return result;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Film film = (Film) o;
if (maxLength != film.maxLength) return false;
if (minLength != film.minLength) return false;
if (!title.equals(film.title)) return false;
return true;
}
#Override
public int hashCode() {
int result = maxLength;
result = 31 * result + minLength;
result = 31 * result + title.hashCode();
return result;
}
public int getMaxLength() {
return maxLength;
}
public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}
public int getMinLength() {
return minLength;
}
public void setMinLength(int minLength) {
this.minLength = minLength;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
To fix your test to actually use such an implementation (it doesn't really test anything...), you could do:
import java.util.Scanner;
public class test {
public static void main (String[] args){
Film lastFilm = null; // arbitrary reference to film
Film[] f = new Film[3];
Scanner input = new Scanner(System.in);
for (int i=0;i<3;i++){
f[i] = new Film();
System.out.println("Enter Film Length:");
f[i].setLength(input.nextInt());
input.nextLine();
System.out.println("Enter Title:");
f[i].setTitle(input.nextLine());
}
input.close();
for (int i = 0; i < 3; i++) {
if ( lastFilm != null ) {
// compare the films to test. current to last film
if ( f[i].compareTo(lastFilm) > 0 ) {
System.out.println(f[i].getTitle() + " is greater than " + lastFilm.getTitle()");
}
else if ( f[i].compareTo(lastFilm) < 0 ) {
System.out.println(f[i].getTitle() + " is less than " + lastFilm.getTitle()");
}
else {
System.out.println(f[i].getTitle() + " is equal to " + lastFilm.getTitle()");
}
}
System.out.println(f[i].toString());
lastFilm = f[i];
}
}
}
Something like this can get you started... good luck
Another solution would be to implement Comparable<Film>:
#Override
public int compareTo(Film that) {
return this.length - that.length;
}
And use org.apache.commons.lang3.ObjectUtils#min or org.apache.commons.lang3.ObjectUtils#max like:
Film min = ObjectUtils.min(film1, film2);
Film max = ObjectUtils.max(film1, film2);

Entering multiple things in to one array in java

I am quite new to java but have a project i need to complete and am stuck on a certain part.
I want to allow the user to enter a route including, start destination, an end destination, and a number of stops. I have been able to do this, but then i want the user to have the ability of being able to add the same things again, to the same array. without deleting the existing route
here is the code i have so far
import java.util.Scanner;
import java.util.Arrays;
public class main {
public static void main(String[] args){
menu();
}
public static void menu(){
Scanner scanner = new Scanner(System.in);
System.out.println("enter 1 to input a new route");
int option = scanner.nextInt();
if(option==1){
inputRoute();
}
}
public static void inputRoute(){
Scanner scanner = new Scanner(System.in);
System.out.println("Please Enter Starting Destination");
String startDest = scanner.next();
System.out.println("Please Enter End Destination");
String endDest = scanner.next();
System.out.println("Please Enter Number of stops");
int numberOfStops = scanner.nextInt();
String[] stops = new String[numberOfStops];
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
stops[i-1] = scanner.next();
}
System.out.println(Arrays.toString(stops));
menu();
}
}
however when this runs, if i go back and enter in another route, it will just delete the existing route.
Is there any way of appending the next route to the end of that array or any way of doing this?
thank you
Like crush said. Rather than use a normal array of strings, use an ArrayList<String> object. Or even an ArrayList<String[]> and stash each individual route in there.
First of all you will need to declare the stops array as an instance variable, otherwise you will always be creating a new array whenever you call the method inputRoute().
and then to preserve old entries i can think of two ways-->
--> modify the loop as below...
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
if(stops!=null) //without the if condition it will also append null in the start
stops[i-1]=stops[i-1]+", "+ scanner.next(); // you can you any separator
else
stops[i-1]=scanner.next();
}
--> or you can ArrayList or any other Collection that provides auto increment
Try declaring stops as a global variable. (right below the class line)
Also I would recommend using an ArrayList, List something on those lines
You can't use an array for this (without constantly re-allocating them) as Arrays are fixed in size once created.
Use an ArrayList though and you can add as many items as you like whenever you like.
The easy (and slightly wrong) solution would be to make your array a static array that is defined outside any method. That will get you going (although you will have to make the array big enought.
Other recommendations:
Capatilize your Main class--avoids confusiong (even moreso if you
don't call it main!)
Make your public static void main method do
this: new Main()
Then get rid of all the other statics.
Use a collection instead of an array.
instead of adding each entry into the array separately (which will make EVERYTHING harder for you), create a second class with 3 fields (start, end, stop) and each time you input another record, "new" an instance of the second class, place the three things into the new instance and place that instance on your collection.
It may seem arbitrary and unnecessary right at this minute, but if you have ANY follow-on work to do on this class these things will make your life easier. If any seems confusing or you want to understand why, feel free to ask in the comments.
I think this will help you.
Main file.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
menu();
}
public static void menu(){
List<Route> routeList = new ArrayList<Route>();
Scanner scanner = new Scanner(System.in);
System.out.println("enter 1 to input a new route");
int option = scanner.nextInt();
if(option==1){
routeList.add(inputRoute());
}
System.out.println("Complete list of routes is "+routeList);
}
public static Route inputRoute(){
Route route = new Route();
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter the name of the route");
String name = scanner.next();
route.setName(name);
System.out.println("Please Enter Starting Destination");
String startDest = scanner.next();
route.setStartLocation(startDest);
System.out.println("Please Enter End Destination");
String endDest = scanner.next();
route.setEndLocation(endDest);
System.out.println("Please Enter Number of stops");
int numberOfStops = scanner.nextInt();
if(numberOfStops > 0){
route.setStopList(new ArrayList<String>());
for(int i = 1; i<=numberOfStops; i++){
System.out.println("Enter Stop" + i);
route.getStopList().add(scanner.next());
}
System.out.println("current entered route is "+route);
menu();
}
return route;
}
}
Route file:
import java.util.List;
public class Route {
String name ;
String startLocation;
String endLocation;
List<String> stopList;
public Route() {
}
public Route(String name, String startLocation, String endLocation, List<String> stopList) {
this.name = name;
this.startLocation = startLocation;
this.endLocation = endLocation;
this.stopList = stopList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStartLocation() {
return startLocation;
}
public void setStartLocation(String startLocation) {
this.startLocation = startLocation;
}
public String getEndLocation() {
return endLocation;
}
public void setEndLocation(String endLocation) {
this.endLocation = endLocation;
}
public List<String> getStopList() {
return stopList;
}
public void setStopList(List<String> stopList) {
this.stopList = stopList;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Route route = (Route) o;
if (endLocation != null ? !endLocation.equals(route.endLocation) : route.endLocation != null) return false;
if (name != null ? !name.equals(route.name) : route.name != null) return false;
if (startLocation != null ? !startLocation.equals(route.startLocation) : route.startLocation != null)
return false;
if (stopList != null ? !stopList.equals(route.stopList) : route.stopList != null) return false;
return true;
}
#Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (startLocation != null ? startLocation.hashCode() : 0);
result = 31 * result + (endLocation != null ? endLocation.hashCode() : 0);
result = 31 * result + (stopList != null ? stopList.hashCode() : 0);
return result;
}
#Override
public String toString() {
return "Route{" +
"name='" + name + '\'' +
", startLocation='" + startLocation + '\'' +
", endLocation='" + endLocation + '\'' +
", stopList=" + stopList +
'}';
}
}

Adding String to 2D Arraylist using for loop and if statement

Ran into a little problem and I'm not entirely sure why this code won't work.
I have a 2d arraylist:
List<List<String>> matrix = new ArrayList<List<String>>();
I have a button that adds an arraylist to the matrix based on user input. But before user input is added, I need the button to search for if that string already exists.
The code I have doesn't produce any errors, but it doesn't seam to discriminate between existing and none existing strings except for the very first element. It adds everything the user puts in regardless of it's existence. Also the code will only function if the matrix array already has some elements in it, if the matrix is empty, the code won't work at all. What am I doing wrong?
String name = NameTXT.getText();
String amount = CountTXT.getText();
for (int i = 0; i < matrix.size(); i ++){
String search = matrix.get(i).get(0);
if (name.equals(search)){
OutputTXT.setText("Item already exists");
break;
} else {
List<String> col = new ArrayList<String>();
col.add(name);
col.add(amount);
matrix.add(col);
OutputTXT.setText(amount +" "+ name +" added");
break;
}
}
break; means that you completely stop the for loop. You can use continue if you just want to go to the next item in the matrix.
separate searching for item and item insertion:
String name = NameTXT.getText();
String amount = CountTXT.getText();
// searching for product
boolean isNewItem = true;
for (int i = 0; i < matrix.size(); i++){
String search = matrix.get(i).get(0);
if (name.equals(search)){
OutputTXT.setText("Item already exists");
isNewItem = false;
break;
}
}
// insert if new item
if ( isNewItem ) {
List<String> col = new ArrayList<String>();
col.add(name);
col.add(amount);
matrix.add(col);
OutputTXT.setText(amount +" "+ name +" added");
}
actually, it would be better to design in abstract way and use the language tools to solve your problem, for example the list would be easier to work if its List of item:
class Item {
private String name;
private String amount;
public Item(String name, String amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return this.name;
}
public String getAmount() {
return this.amount;
}
#Override
public boolean equals(Object other) {
if ( other == this )
return true;
if ( other == null )
return false;
if ( other.getClass() != this.getClass() )
return false;
Item otherItem = (Item) other;
return otherItem.getName().equals(this.name);
}
}
then the list would be:
List<Item> items = new ArrayList<Item>();
when you need to search:
Item item = new Item(NameTXT.getText(), CountTXT.getText());
if ( !items.contains(item) ) {
items.add(item);
}
Uhhh... i would try foreach syntax instead of a classical for if i were you. I guess that's why your code does not work when the matrix is empty : you cant't do this with an empty arraylist :
matrix.get(i).get(0);
Also , the else clause is embedded inside the if clause , so i'm not sure how the code compiles.
You should try something like :
for(List<String> elem : matrix){
if(elem.get(0).equals(name)){
// do stuff
}
else{ //do other stuff }
}
Why loop over every item in the list and not just use contains:
for(List<String> list : matrix){
if(!list.contains(name){
//add element to matrix
}
}

Categories