Making an equivalence in Java - java

As you will probably see from my code I'm quite new with this. I am trying to write a simple program to retrieve the friends of one person. Here is my code:
public class Person {
private String name;
private String friends;
public Person(String aName) {
name = aName;
friends = "";
}
public String getFriends() {
return friends;
}
public void addFriend(Person friend) {
friends = friends + " " + friend.name;
}
public void unfriend(Person nonFriend) {
friends = friends.replace(" " + nonFriend.name, "");
}
public static void main(String[] args) {
Person dana = new Person("Dana");
Person gina = new Person("Gina");
Person john = new Person("John");
dana.addFriend(gina);
dana.addFriend(john);
john.addFriend(gina);
john.addFriend(dana);
john.unfriend(dana);
System.out.println("Dana's friends are: " + dana.getFriends());
System.out.println("Gina's friends are: " + gina.getFriends());
System.out.println("John's friends are: " + john.getFriends());
}
}
Everything works, but I do not know how to create a method that will say:
If Gina is both Dana's and John's friend then clearly Gina's friends will be Dana and John. I know that I can add two lines there gina.addFriend(dana) and gina.addFriend(john), to accomplish the same result, but I would like to know what will the method be for that. Thanks in advance.

First of all, make friends an ArrayList<Friend>.
private ArrayList<Friend> friends;
This has several advantages, including being easier to use and storing the Persons themselves rather than just their names.
Then, change the addFriend method to go in both directions:
public void addFriend(Person friend) {
friends.add(friend);
friend.friends.add(this);
}
In this way, friendships will automatically go back and forth. You should also change unfriend:
public void unFriend(Person friend) {
friends.remove(friend);
friend.friends.remove(this);
}
EDIT: as per a comment above, a set would actually be better, as it can only have one of each value.

I would use a Set, and add a unique Id to person to get around the problem of multiple people having the same name.
Your class will then look like:
public class Person
{
private final String personId;
private final String name;
private final Set<Person> friends;
public Person(String personId, String name) {
super();
this.personId = personId;
this.name = name;
this.friends = new HashSet<Person>();
}
public void addFriend(Person friend) {
if(friend != null && !friends.contains(friend)) {
this.friends.add(friend);
// Optional : if it is a two-way relationship that doesn't need approving etc
friend.addFriend(this);
}
}
public void unfriend(Person nonFriend)
{
if(nonFriend != null && friends.contains(nonFriend)) {
this.friends.remove(nonFriend);
// Optional : if it is a two-way relationship that doesn't need approving etc
nonFriend.unfriend(this);
}
}
public Set<Person> getFriends()
{
return friends;
}
#Override
public String toString() {
return "Person [name=" + name + "]";
}
public static void main(String[] args)
{
Person dana = new Person("D001", "Dana");
Person gina = new Person("G001", "Gina");
Person john = new Person("J001", "John");
dana.addFriend(gina);
dana.addFriend(john);
john.addFriend(gina);
john.addFriend(dana);
john.unfriend(dana);
System.out.println("Dana's friends are: "+dana.getFriends());
System.out.println("Gina's friends are: "+gina.getFriends());
System.out.println("John's friends are: "+john.getFriends());
}
// Equals and Hashcode are very important when using 'contains' and other Set-based methods
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((personId == null) ? 0 : personId.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;
Person other = (Person) obj;
if (personId == null) {
if (other.personId != null)
return false;
} else if (!personId.equals(other.personId))
return false;
return true;
}
}

i would suggest to use an arrayList of persons/friends instead of one string.
ArrayList<Person> friends = new ArrayList<Person>;
you add friends by typing:
public void addFriend(Person newFriend){
friends.add(newFriend);
newFriend.friends.add(this);
}
you delete friends by typing:
public void unfriend(Person noFriend){
for(int i = 0; i < this.friends.size(); i++){
if(this.friends.get(i).name.equals(noFriend.name){
this.friends.delete(i);
}
}
for(int i = 0; i < noFriend.friends.size(); i++){
if(noFriend.friends.get(i).name.equals(this.name){
noFriend.friends.delete(i);
}
}
}
to show the whole list of friends:
public void showFriends(){
for(int i = 0; i < this.friends.size(); i++){
System.out.println(this.friends.get(i));
}
}

Related

Java compare object element and if "name" attribute is same print it once

Is it possible to compare attributes of objects in a list & if the attribute "name" happens to be the same then print out the one that is older (with the rest that does not have same name) and if their name & age happens to be the same then print out one of them (with the rest that does not have same name)? I need to compare a list with objects. I sorted the list and started with nestled for-loops but then got stuck. Are there better ways of doing this? Maybe placing some method in the Person class or another way?
enter code here
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
public class Main {
public static void main(String[] args){
Person[] persons = new Student[4];
persons[0] = new Person("Erik",20);
persons[1] = new Person("Bob",21);
persons[2] = new Person("Erik",25);
persons[3] = new Person("Fredrik",20);
Arrays.sort(persons, Comparator.comparing(Person::getName));
for (int i = 0; i<persons.length; i++)
for(int j = 0; j<i; j++){
if (persons[i].getAge() == persons[j].getAge())
}
//output: Bob, Erik, Fredrik
}
}
Since you only want each name to be once, and the oldest, you can create what's called a HashMap, ( Key-> value association with unique key) in which you store only the oldest person
Once you have this hashmap, you then can iterate through it to print exactly what you want
Example :
public static void main(String[] args){
Person[] persons = new Student[4];
persons[0] = new Person("Erik",20);
persons[1] = new Person("Bob",21);
persons[2] = new Person("Erik",25);
persons[3] = new Person("Fredrik",20);
HashMap<String, Integer> oldest_people = new HashMap<>();
for (Person p: persons){
int person_age = oldest_people.getOrDefault(p.getName(), -1);
if (person_age != -1) {
if (p.getAge() > person_age) {
oldest_people.put(p.getName(), p.getAge());
}
}
else {
oldest_people.put(p.getName(), p.getAge());
}
}
for (Map.Entry<String, Integer> entry : oldest_people.entrySet()) {
System.out.println(entry.getKey() + " age : "+entry.getValue().toString());
}
}
Alternate approach based on your program,
override these below methods on a Person class
#Override
public int hashCode() {
return name.hashCode();
}
#Override
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof Person)) return false;
Person p = (Person) obj;
if(this.name.equals(p.getName())) return true;
return false;
}
And you can add custom comparator to sort person on the array
Comparator<Person> comparePerson = new Comparator<Person>() {
#Override
public int compare(Person p1, Person p2) {
//name in ascending order
int nameCompare = p1.getName().compareTo(p2.getName());
//age in descending order means from higher age
int ageCompare = Integer.compare(p2.getAge(), p1.getAge());
return nameCompare == 0 ? ageCompare : nameCompare;
}
};
Arrays.sort(persons, comparePerson);
After, you can find unique Person. Below, the Set collection will only add
a unique Person, this time oldest age person will add.
Set<Person> personSet = new HashSet<>();
for(Person p : persons) {
if(!personSet.contains(p)) personSet.add(p);
}
Now, you can get a unique Person in collection.

Use 2 methods 1. Check if object exists 2. Add object

I was wondering how do I go about to create 2 methods,
1. Which does the checking, if the object already exists within the array (based on one of the parameters).
2. Secondly add a method which allows the user / me to add objects into the array when the previous (1st method) returns false.
Here is my try:
public class Book {
String name;
int isbn;
public Book(String e, int iNr) throws LibraryException{
if(e.equals("")){
throw new LibraryException("Blank / empty name is not allowed!");
}
else if(iNr < 1 || iNr > 9000){
throw new LibraryException("The isbn number is outside the allowed range (1 - 9000)! ");
}
setName(e);
setIsbn(iNr);
}
public boolean equals(Object obj){
if(obj instanceof Book){
isbn = (isbn)obj;
return true;
}
return false;
}
public String getName() {
if(name == null || name == ""){
System.out.print("Does not exist!");
}
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIsbn() {
if(isbn < 0){
System.out.print("ISBN (LIBRI) EXCEPTION TO BE ADDED!");
}
return isbn;
}
public void setIsbn(int isbn) {
this.isbn = isbn;
}
}
.
public class Library
{
String name;
Book[] books;
int nrBooks = 0;
public Library(String name, int nrBooks) throws LibraryException {
if(name.equals("")){
throw new LibraryException("Blank names is not allowed");
}
if(nrBooks < 500){
throw new LibraryException("The number of books needs to be greater than 500!");
}
this.name = name;
this.nrBooks = nrBooks;
this.books = new Book[nrBooks];
}
public void addBook(Book book) throws LibraryException {
if(indexOf(book) == -1){
if(nrBooks < books.length)
books[nrBooks++] = book;
}
}
private int indexOf(Book book)throws LibraryException {
if(nrBooks < Book[].length){
}
return -1;
}
public static void main(String[]args) throws LibraryException{
Library b = new Library("Sami Frasheri", 700);
b.addBook(new Book("Paul Colhen - Alchemist", 1));
b.addBook(new Book("Paul Colhen - Winners Stand ALone", 2));
b.addBook(new Book("Paul Colhen - The river Piedra I sat and I cried", 3));
System.out.print(b);
}
}
Tried ArrayList In Java?.
They will be able to solve almost all of the problems you are facing. Have a look at contains and add.
Please Note, you must override the hashCode and equals method of your Book object for it to work effectively.
I suggest you use an ArrayList of Book. It will solve all of your problems.
public class Library {
private String name;
private ArrayList<Book> books;
private int maxNumberOfBooks;
public Library(String name, int maxNumberOfBooks) {
this.name = name;
this.maxNumberOfBooks = maxNumberOfBooks;
this.books = new ArrayList<Book>();
}
public void addBook(Book book) {
if (!books.contains(book)) {
books.add(book);
}
}
}
If you need to check both parameters, then do something like:
public void addBook(Book book) {
for (Book b : books) {
if (b.getName().equals(book.getName())) {
return; // another book has the same name
}
if (b.getIsbn() == book.getIsbn()) {
return; // another book has the same ISBN
}
}
books.add(book);
}
The size of an array can't be modified. If you want to add an element, you have to instantiate a new array.
public void addBook(Book book) {
int oldN = books.length;
books = Arrays.copyOf(books, oldN + 1);
books[oldN] = book;
return books;
}
This function could replace indexOf(). It looks for the element in your array.
private boolean contains(Book book) {
for (Book b : books) {
if (b != null && book.equals(b))
return true;
}
return false;
}
I would suggest something like this:
public void addBook(Book book) throws LibraryException {
if(indexOf(book) == -1){//book does not exist
if(nrBooks < (books.length-1)){
books[nrBooks] = book;
++nrBooks;
} else {
throw new LibraryException("Not space for more books.");
}
}
}
private int indexOf(Book book)throws LibraryException {
for(int i=0;i<books.lenght;++i){
if(books[i].getName().equals(book.getName()) && books[i].getIsbn==book.getIsbn){
return i;
}//if
}//for
//else
return -1;
}

Trying to make a 2d array program to store a list of Car objects

Struggling with a little project I've set myself to learn Java. My goal is to create a program to store a list of Car objects. Then to allow the user to search for a particular car and output all of them if they exist. The car object should contain model name, registration number, vin and colour. Here is what I have so far:
package carObjects;
public class cars {
public static int length;
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public cars(String string, String string2, int i) {
}
public String toString() {
return "Model Name: " + modelName + "Registration Number: " + regNumber
+ "Vin" + vin + "Car Colour: " + carColour;
}
public String getLast() {
return modelName;
}
}
for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
for (cars p : cars) {
System.out.println(p.getLast());
}
}
}
Here are some of the things you would need to do:
Since you want to allow searching, you will need to expose accessors to the properties which you would like the user to search for. For instance, if you want to allow users to search by model, you will need to expose the model property. You seem to be doing this through the getLast() method, however, the name is confusing.*
The problem with this code: for (int i = 0; i < cars.length; i++) {
cars[i] = new cars("A", "B", 10);
}
Is that it is creating a series of identical objects. You could use the value of i to provide some dummy, changing values. This will allow you to test that your search is indeed working.
Constructor names should start with an upper case, just like class names.
cars(String string, String string2, int i): Please provide meaningful names to your variables. This will make your code easier to read.
You will need to assign the variables you are getting through your constructor. As is, at the moment your fields will not be initialized to what you are providing.
To create a 2D array, you will need to use the following syntax: Car[][] carArr = new Car[5][5]. This will create a 5x5 array of type car. To iterate over it, you will need to use a nested loop:
for(int i = 0; i < carrArr.length; i++) {
for (int j = 0; j < carrArr[i].lenght;j++) {
...
}
}
* The usage of getters and setters allow you to control which object properties are exposed and how can users interact with them.
The best would be to separate your exercise in two different classes:
class Car {
private String modelName;
private String carColour;
private int regNumber;
private int vin;
public int getVin() {
return vin;
}
public void setVin(int vin) {
this.vin = vin;
}
// other getter/setter
#Override
public String toString() {
return "Car: " + getVin();
}
#Override
public int hashCode() {
return vin;
}
#Override
public boolean equals(Object obj) {
return (obj != null)
&& (obj instanceof Car)
&& ((Car) obj).getVin() == this.getVin();
}
}
CarSet class has the searching methods:
class CarList extends HashSet<Car> {
public Car serarchByVin(int vin) {
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getVin() == vin) {
return c;
}
}
return null;
}
public CarSet searchByModel(String model) {
CarSet result = new CarSet();
List<Car> list = new ArrayList<>(this);
for (Car c : list) {
if (c.getModelName()== model) {
result.add(c);
}
}
return result;
}
#Override
public String toString() {
String result = "carList: ";
for (Car c : this) {
result += c;
}
return result;
}
}

Get Common Element in Two Lists of Book

I have two array lists that store instances of a class called Book. I am trying to get the book/books that is inside both lists.
This is a search feature that allows you to search for a book by entering the book's ISBN, Name and Author. The list 'resultA' contains the books with the inputted ISBN and Name while the other list 'resultB' contains the books written by the inputted author. To get the final result I need to get the book that is inside both arrays.
I have tried using the retainAll() function but I found that it doesn't work on lists with instances stored.
List<Book> resultA = BookManager.getBooksWhere("book_ISBN", ISBN, "book_name", bookName);
List<Book> resultB = BookManager.getBooksByAuthors(authors);
resultB.retainAll(resultA);
searchResults = resultA;
Is there some other function I can use instead to get the common book?
(Update)
Sorry, Here is the Book class:
public class Book
{
private int bookID;
private String bookISBN;
private String category;
private int libId;
private String name;
#Override
public String toString()
{
String output = bookISBN + " - " + name + " - " + category + " - ";
return output;
}
public int getBookID()
{
return bookID;
}
public void setBookID(int bookID)
{
this.bookID = bookID;
}
public String getBookISBN()
{
return bookISBN;
}
public void setBookISBN(String bookISBN)
{
this.bookISBN = bookISBN;
}
public int getLibId()
{
return libId;
}
public void setLibId(int libId)
{
this.libId = libId;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
(Update)
I did not know that I had to override the Books class for this to work and thanks for pointing that out DNA and pbabcdefp. I have looked up on how to do it and it has worked correctly, the common book is being taken out from both lists.
This was inserted in the book class and uses their unique id to compare if books are equal.
#Override
public boolean equals(Object o)
{
if (o == null)
return false;
if (getClass() != o.getClass())
return false;
final Book otherBook = (Book) o;
if (this.bookId != otherBook.bookId)
{
return false;
}
return true;
}
Assuming you defined an equals function for the Book class, here is a function that can get the common elements in two arrays:
public static <T> List<T> getCommonElements(List<T> list1, List<T> list2) {
List<T> resultsList = new ArrayList<>();
for (T element1: list1) {
for (T element2: list2) {
if (element1.equals(element2)) {
resultsList.add(element2);
}
}
}
return resultsList;
}
This looks like a school question. With that, I doubt you are looking for an answer with generics or comparators or overriding the compareTo or equal method.
Hence, this is what you can do:
for(int x=0; x<listA.size(); x++)
for(int y=0; y<listB.size(); y++)
if(listA.get(x).getISBN().equals(listB.get(y).getISBN()))
return listA.get(x);
Instead of using equals to compare, you get use their ISBN which is supposed to be their unique id. Alternatively, you can override the equals method within the Book class to compare the ISBN.

How to in a class, use an attribute of a different class to find out the other attribute. (java)

Sorry if i'm being vague here, i'll post my code for you guys too. I'm a beginner so go easy on me.
I have a class called student, it has an int id, and another String name. I have created another Class for the GUI. It has a window that pops up and has a field for the id. I want to enter the ID and get the Name from that ID. I have no idea of going about this and i've been stuck for hours. I'm kind of slow to catch on, so could someone help me? I'm not very good at inheritance. (also, i have two other classes, but i don't think they would be of any help here.
STUDENT CLASS
public class Student {
private int id;
private String name;
private ArrayList<Course> regCourses;
public int getId() {
return id;
}
public String getName() {
return name;
}
public ArrayList<Course> getRegCourses() {
return regCourses;
}
public Student(int i, String n) {
id = i;
name = n;
regCourses = new ArrayList<Course>();
}
public String toString() {
String answer = id + " " + name + " - Registered Courses: ";
if (regCourses.size() == 0)
answer += "NONE";
else {
for (int i = 0; i < regCourses.size(); i++) {
answer += regCourses.get(i).getDepartment().getId()
+ regCourses.get(i).getCode();
if (i != regCourses.size() - 1)
answer += ", ";
}
}
return answer;
}
public void registerFor(Course c) {
if (!isRegisteredInCourse(c)) {
// Register
regCourses.add(c);
if (!c.getClassList().contains(this)) {
c.getClassList().add(this);
if (!c.getDepartment().getStudentList().contains(this))
c.getDepartment().getStudentList().add(this);
}
}
}
public boolean isRegisteredInCourse(Course c) {
return regCourses.contains(c);
}
}
And here's the search code in another class.
public class MainGUIWindow extends JFrame implements ActionListener {
JLabel studentID, studentName, currentRegCourses;
JButton search, regForCourse, withdraw;
JTextField idField, nameField;
JScrollPane courseScrollList;
public MainGUIWindow(String title) {
super(title);
//GUI STUFF
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == search) {
if (idField.getText() != null) {
int id = Integer.parseInt(idField.getText());
Student temp = null;
//CODE GOES HERE
}
}
}
public static void main(String[] args) {
new MainGUIWindow("Student Administration System").setVisible(true);
Also, if need be, these all my java files.
http://www.filehosting.org/file/details/426633/JavaCode-SO.zip
Edit: There are 2 more Classes that are my test programs that have data in them.
You could store the Students in a Hashmap or treemap and then look them up
i.e
HashMap<Integer,Student> studentMap = new HashMap<>();
studentMap.put(matt.getId(), matt);
.....
Student s = studentMap.get(lookupId); /* Retrieve based on Student id*/

Categories

Resources