Removing Duplicate Entries in Array - Java - java

For Java practice, I am trying to create a method inside my EmployeesDirectory Class that:
Removes Duplicate entries from the array
The array should be the same length after removing duplicates
Non-Empty entries should be making a contiguous sequence at the beginning of the array - and the actualNum should keep a record of the entries
Duplicate Means: Same Name, Position and Salary
Here is my Current Code:
I am unsure on how to implement this - any help would be appreciated
class EmployeeDirectory {
private Employee dir[];
private int size;
private int actualNum;
public EmployeeDirectory(int n) {
this.size = n;
dir = new Employee[size];
}
public boolean add(String name, String position, double salary) {
if (dir[size-1] != null) {
dir[actualNum] = new Employee(name, position, salary);
actualNum++;
return true;
} else {
return false;
}
}
}

I'd rather you did not write a distinct method for removing duplicates. If I were you, I would search for duplicates in add method and then instantly decide whether I need to add Employee.
Also, why don't you use Sets (link for HashSet) instead of arrays for your purpose? Sets by their own definition disallow adding duplicates, so they seem to be appropriate as a solution

First of all, Override equals and hashCode methods in Employee class as follow
#Override
public boolean equals(Object other) {
if(this == other) return true;
if(other == null || (this.getClass() != other.getClass())){
return false;
}
Employee guest = (Employee) other;
return Objects.equals(guest.name, name)
&& Objects.equals(guest.position, position)
&& Objects.equals(guest.salary, salary);
}
#Override
public int hashCode() {
return Arrays.hashCode(new Object[] {
name,
position,
salary
});
}
Then you can use Stream API distinct method to remove duplicates
Returns a stream consisting of the distinct elements (according to
Object.equals(Object)) of this stream.
You can do it like so
Employee e1 = new Employee("John", "developer", 2000);
Employee e2 = new Employee("John", "developer", 2000);
Employee e3 = new Employee("Fres", "designer", 1500);
Employee[] allEmployees = new Employee[100];
allEmployees[0] = e1;
allEmployees[1] = e2;
allEmployees[2] = e3;
allEmployees = Arrays.asList(allEmployees).stream().distinct()
.toArray(Employee[]::new);
Arrays.asList(allEmployees).forEach(System.out::println);
Output: (keeping both empty and non-empty entries)
John developer 2000.0
Fres designer 1500.0
null

Unfortunately, I have not got the Employee class to verify my code, but try this:
void removeDuplicates() {
int length = dir.length;
HashSet set = new HashSet(Arrays.asList(dir));
dir = new Employee[length];
Employee[] temp = (Employee[]) set.toArray();
for (int index = 0; index < temp.length; index++)
dir[index] = temp[index];
}
The code must remain the size of array after deletion the duplicates. At the beginning of array there must be valid Employees, at the end - nulls.
And don't forget to add this at the beginning of your .java file
import java.util.Arrays;
import java.util.HashSet;

If your task states as "remove duplicates from array" (i. e. you cannot use ArrayList or control when adding items), you can use the following approach:
public void removeDuplicates() {
Set<Employee> d = new HashSet<>(); // here to store distinct items
int shift = 0;
for (int i = 0; i > dir.length; i++) {
if (d.contains(dir[i])) { // duplicate, shift += 1
shift++;
} else { // distinct
d.add(dir[i]); // copy to `d` set
dir[i - shift] = dir[i]; // move item left
}
}
for (int i = d.size(); i < dir.length; i++)
dir[i] = null; // fill rest of array with nulls
actualNum = d.size();
}
Here, shift variable stores number of duplicates found in the array so far. Every distinct item is moved to shift positions left in order to make sequence continuous while keeping initial ordering. Then remaining items are altered to nulls.
To make hash-based collections work with Employee instances correctly, you also need to override hashCode() and equals() methods as follows:
public class Employee {
//...
#Override
public int hashCode() {
return Objects.hash(name, position, salary);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (!o.getType().equals(this.getType()) return false;
Employee e = (Employee) o;
return Objects.equals(e.name, name)
&& Objects.equals(e.position, position)
&& Objects.equals(e.salary, salary); // or e.salary == salary, if it primitive type
}
}

Related

Bubble Sort objects

I need to sort my grocery inventory by name by using bubble sort.
Apparently, my code is not sorting the list by name.
BTW, the data stored inventory comes from a file input.
Here is my code.
public void sortInventoryByName() {
//TODO: use bubble sort and compareTo
int n = inventory.size();
GroceryItem temp;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (inventory.get(j).compareTo(inventory.get(j + 1)) > 0) {
temp = inventory.get(i);
inventory.set(i, inventory.get(i + 1));
inventory.set(i + 1, temp);
}
}
}
}
Here is my compareTo method from my superclass (GroceryItem)
#Override
public int compareTo(Object o) {
if(getClass() != o.getClass()) {
throw new IllegalArgumentException();
}
else {
GroceryItem other = (GroceryItem) o;
return (this.name.compareTo(other.name));
}
}
Looks like you have some mismatch for comparing the right values.
There are two ways of implementing a bubble sort algorithm with two for loops.
Below made the first loop incremented barrier variable and second is decrementing index.
Thus with every iteration of the outer loop, the lowest value will be moved to the first place (like the smallest bubble will be moved first). The next iteration will skip this first element. And it will last till the list full list will be over.
Your example shows opposite behaviour -> with every iteration for the outer loop the highest element in a list is moved to the end.
It isn't so important how exactly do you want to iterate the inner for loop. The final sorted result is our aim.
Code snippet:
public void sortInventoryByName() {
int n = inventory.size();
for (int barrier = 0; barrier < n - 1; barrier++) {
for (int index = n - 2; index >= barrier; index--) {
if (inventory.get(index).compareTo(inventory.get(index + 1)) > 0) {
GroceryItem temp = inventory.get(index);
inventory.set(index, inventory.get(index + 1));
inventory.set(index + 1, temp);
}
}
}
}
Your implementation of compareTo() should work fine. So, inventory list should be sorted correctly.
A few notices according to your code:
you don't need to declare temp variable outside of loops. It is just a temporary variable for swapping two values. Inline declaration and usage will be enough.
would suggest adding more meaningful names for loop variables instead of just i and j. It increases code readability and understanding in the future
else block is redundant at compareTo()
#Override
public int compareTo(Object o) {
if (getClass() != o.getClass()) {
throw new IllegalArgumentException();
}
GroceryItem other = (GroceryItem) o;
return this.name.compareTo(other.name);
}
I filled in the missing parts of your code. You should read How do I ask a good question and also the link to How to create a Minimal, Reproducible Example.
The below code is the GroceryItem class which only contains a single member, i.e. name, which is the name of the grocery item. Since your question only deals with manipulating this member, I did not try to guess what other data the class needs.
Explanations after the code.
import java.util.ArrayList;
import java.util.List;
public class GroceryItem implements Comparable<GroceryItem> {
private String name;
public GroceryItem(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override // java.lang.Comparable
public int compareTo(GroceryItem other) {
if (other == null) {
return 1;
}
else {
String otherName = other.getName();
if (name == null) {
if (otherName == null) {
return 0;
}
else {
return -1;
}
}
else {
if (otherName == null) {
return 1;
}
else {
return name.compareTo(otherName);
}
}
}
}
#Override // java.lang.Object
public boolean equals(Object other) {
boolean equal = false;
if (other instanceof GroceryItem) {
GroceryItem otherItem = (GroceryItem) other;
if (name == null) {
equal = otherItem.getName() == null;
}
else {
equal = name.equals(otherItem.getName());
}
}
return equal;
}
#Override // java.lang.Object
public int hashCode() {
return name == null ? 0 : name.hashCode();
}
#Override // java.lang.Object
public String toString() {
return name;
}
public static void main(String[] args) {
List<GroceryItem> inventory = new ArrayList<>();
inventory.add(new GroceryItem("apple"));
inventory.add(new GroceryItem("pear"));
inventory.add(new GroceryItem("banana"));
inventory.add(new GroceryItem("orange"));
inventory.add(new GroceryItem("beetroot"));
inventory.add(new GroceryItem("onion"));
inventory.add(new GroceryItem("lettuce"));
inventory.add(new GroceryItem("carrot"));
inventory.add(new GroceryItem("guava"));
inventory.add(new GroceryItem("lychee"));
inventory.add(new GroceryItem("kiwi"));
int n = inventory.size();
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (inventory.get(j).compareTo(inventory.get(j+1)) > 0) {
// swap inventory[j+1] and inventory[j]
GroceryItem temp = inventory.get(j);
inventory.set(j, inventory.get(j+1));
inventory.set(j+1, temp);
}
}
}
System.out.println();
}
}
The above code creates a List of GroceryItem objects that contains eleven elements. After populating the List, the bubble sort is performed in the two, nested for loops. Finally the sorted List is printed.
Note that class GroceryItem also implements method toString() so as to make the output human-readable when printing an instance of GroceryItem.
If, in future, you need to use GroceryItem as the key for a java.util.HashMap, then GroceryItem will need to override method hashCode() and if a class overrides method hashCode() then it should also override method equals(). Hence that is why the above code includes those overridden methods. Note that none of those methods – equals(), hashCode() and toString() – are required for the bubble sort.
The oputput when running the above code is:
[apple, banana, beetroot, carrot, guava, kiwi, lettuce, lychee, onion, orange, pear]

Ordering the results of an file with ArrayList and compareTo

I have to order an arrayList that contains lines from a file by account ID and then by salary to get this result:
CuentaAhorro : 11111111A (Alicia) Saldo 111,11
CuentaAhorro : 12345678A (Lucas) Saldo 5100,00
CuentaCorriente: 22222222B (Peio) Saldo 222,22
CuentaAhorro : 33333333C (Isabel) Saldo 4433,33
CuentaCorriente: 33333333C (Isabel) Saldo 3333,33
CuentaAhorro : 87654321A (Asier) Saldo 3000,00
My arrayList calls the compareTo method from Bank.java.
public void ordenarCuentas() {
Collections.sort(cuentas);
}
The call is to the method compareTo in an abstract class called Account with the comparable interface:
#Override
public int compareTo(Cuenta unaCuenta) {
Cliente unTitular = unaCuenta.titular;
if(unTitular.toString().equals(unaCuenta.titular.toString()) == true) {
return 0;
// if(saldo < unaCuenta.saldo) {
// return -1;
// } else if (saldo > unaCuenta.saldo) {
// return 1;
// } else {
// return 0;
// }
}
return -1;
}
I need to check if the object 'Cuenta unaCuenta' passed as a parameter has the same account number as another and then sort by the amount of money in the account, however I am not sure how to get the condition right, as you can see, with the commented if I get the salary in the right descending order but not the account IDs.
The object Cuenta unaCuenta contains titular which contains account number and name.
The object Cliente unTitular contains the account number and name.
Could somebody lend me a hand please?
I am not able understand it very clearly because of language barrier
But if you have a arraylist you can call sort method on it an pass a comparator to get the desired sorting , something like below.
It is just to give you an idea
ArrayList<String> list = new ArrayList<>();
list.sort(new Comparator() {
#Override
public int compare(Object o1, Object o2) {
if(o1.account.equals(o2.account)) return 0;
return o1.amount - o2.amount;
}
});
as Lambda
ArrayList<String> list = new ArrayList<>();
list.sort((o1,o2) ->
if(o1.account.equals(o2.account)) return 0;
return o1.amount - o2.amount;
});
Thank you everyone for the comments. Next time i'll translate the Spanish code to English. I'll post my solution incase someone comes across this question.
(in my case I had to use a comparable interface and a compareTo method).
#Override
public int compareTo(Account anAccount) {
String b = this.title.toString();
Client aTitle = anAccount.title;
String c = aTitle.toString();
if(b.compareTo(c) == 0) {
if(balance == anAccount.balance) {
return 0;
} else if (balance < anAccount.balance) {
return 1;
} else {
return -1;
}
}
return b.compareTo(c);
}
As stated, I had to compare both object values first, if they are the same I then check the condition of the balance to change the order.
-1 = object is less than the parameter.
0 = when both objects are the same.
1 = the object is more than the parameter.
And I called the method from the Bank.java class with:
Collections.sort(cuentas);
Where cuentas is the ArrayList.

Move an element up in the list using Comparator

I have an ArrayList in Java :
{"PatMic", "PatientDoc", "Phram", "Patnet", "PatientA"}
All the elements have a number assigned : PatMic = 20, PatientDoc = 30, Phram = 40, Patnet = 50, PatientA = 60.
And my current Comparator :
Comparator<String> comparator = new Comparator<String>() {
#Override
public int compare(final String o1, final String o2) {
final int numbr1 = getElementNumber(); //Returns element's number in a list
final int numbr2 = getElementNumber();
if (numbr1 > numbr2 ) {
return 1;
} else if (numbr1 < numbr2 ) {
return -1;
}
return 0;
}
};
Collections.sort(strings, comparator);
I do not want to change the assigned numbers to each element but would want to move the element PatientA in between PatMic and PatientDoc so the modified list should look like :
{"PatMic", "PatientA" "PatientDoc", "Phram", "Patnet"}
Could someone please suggest how to achieve this? I tried many ways to modify the existing Comparator logic but in vain. Thank you.
You are trying to sort based on some inherent value associated with a String. Therefore, sorting on a String itself is probably not correct. What you probably want to use is either a custom object (implement equals, hashCode and the interface Comparable), or an enum type. This will allow you to change the internal state of these objects explicitly, which will manifest itself naturally when using a Comparator. For example, using a class:
class MyClass implements Comparable
{
private String name;
private int value;
//Constructor
public MyClass(String s, int v)
{
name = s;
value = v;
}
//Getters and setters
//Implement comparing method
}
Then you can use these objects in place of your Strings:
//...
MyClass patMic = new MyClass("PatMic", 20);
// So on..
First, you should give you comparator sufficient knowledge about what it should do. I mean you should have some data available to comparator that says something like "okay, sort them all by associated number except this one - place it right here". "Right here" could be anything that points exact position, I gonna choose "before that element".
So here we go
public void sortWithException(List<String> data, final Map<String, Integer> numbers, final String element, final String next) {
Collections.sort(data, new Comparator<String>() {
#Override
public int compare(String first, String second) {
if (first.equals(element) || second.equals(element)) { //the exception
Integer nextNumber = numbers.get(next);
Integer firstNumber = numbers.get(first);
Integer secondNumber = numbers.get(second);
if (first.equals(element)) {
if (next == null) // placing the exception after ANY element
return 1;
return secondNumber >= nextNumber ? -1 : 1; //placing the element before next and after all next's predecessors
} else { // second.equals(element)
if (next == null)
return -1;
return firstNumber >= nextNumber ? 1 : -1;
}
} else { //normal sort
return numbers.get(first) - numbers.get(second);
}
}
});
}
and call it like sortWithException(data, numbers, "PatientA", "PatientDoc")
Note that i used Map for associated numbers, you should probably use your own method to get those numbers.

how to make a connected list of elements in Java

i want to make a connected list of Student elements. The class Student must have only two fields(name and codeNumber).I also created a method to compare the names and if the names are equals then i compare codeNumbers. this is because i must insert the elements low to high.
I created a class like:
class Student
private String name;
private int codeNumber;
public Student(String name, int AM){
this.name = name;
this.codeNumber = codeNumber;
}
public int compareTo(Student other){
int result;
if(other.name.compareTo(this.name) == 0){
result = 0;
return result;
}
if(other.name.compareTo(this.name) < 0){
result = 1;
return result;
}
if(other.name.compareTo(this.name) > 0){
result = -1;
return result;
}
if(other.codeNumber > this.codeNumber){
result = 1;
return result;
}
if(other.codeNumber < this.codeNumber){
result = -1;
return result;
}
}
public String getName(){
return name;
}
public int getcodeNumber(){
return codeNumber;
}
}
And here is the problem. I need a StudentList class to make my own list.
So i created the class but im not sure if i have the right fields in this class.
I created 4 fields:
1.private Student studentElement;
2.private StudentList next = null; a reference to the next element
3.private StudenList head; a reference to the start of the list
4.private int size = 0; to know the number of the elements
And here is my code:
class StudentList{
private Student studentElement;
private StudentList next = null;
private StudentList head;
private int size = 0;
public StudentList(Student listEl){
listElement = listEl;
}
public boolean containsElement(Student p){
StudentList position = head;
while(position != null){
if(StudentElement.getName().equals(p.getName()) && studentElement.getAM() == p.getAM()){
return true;
}
position = position.getNext();
}
return false;
}
}
This is my code. Can anyone tell me if i have the right types of fields in my class and help me creating an insert method.
Don't reinvent the wheel.
Prefer using java.util.LinkedList
and add the Student instances in the way you need. This will preserve the order in
which you add to the list
Use one of the Java library list implementations such as ArrayList or LinkedList which do precisely what you want, no point in rolling-your-own.
Also learn about Collections.sort() if needed.
Your Student class should also implement the Comparable interface which (by a stroke of luck) has the same signature as your existing compareTo method.

Compare arraylist objects in java

I have list of objects in an arraylist and I need to compare every objects with other objects available in the arraylist;
For Example:
Class Employee {
private String empname;
private Long empid;
private boolean empsex;
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public Long getEmpid() {
return empid;
}
public void setEmpid(Long empid) {
this.empid = empid;
}
public boolean isEmpsex() {
return empsex;
}
public void setEmpsex(boolean empsex) {
this.empsex = empsex;
}
}
public list<Employee> getEmpList() {
List<Employee> empList = new ArrayList<Employee>();
Employee emp = new Employee();
for(...) {
//insert values to emp object for n number of times;
}
empList.add(emp); //add emp.object to empList;
return empList;
}
Now while inserting these values to UI; Need to compare objects in the list; where any two or more objects matches with each other or not?
Based on the assumption that you want to eliminate the duplicates from the list and do not show duplicates on GUI.
Use Set collection, it automatically takes care of duplicates.
A collection that contains no duplicate elements. More formally, sets
contain no pair of elements e1 and e2 such that e1.equals(e2), and at
most one null element. As implied by its name, this interface models
the mathematical set abstraction.
Override equals() and hashcode() methods.
References:
On equals and hashcode in Java
Overriding equals and hashcode
You could override equals method for that class to compare the objects of the same class the way you want.
Default equals method:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Link about overriding equals:
http://javarevisited.blogspot.com/2011/02/how-to-write-equals-method-in-java.html
One simple method of doing this is to just do a double for loop.
public static List<Employee> getList(List<Employee> oldList)
{
List<Employee> empList = new ArrayList<Employee>();
for (int i = 0; i < oldList.size; i++)
{
for (int j = 0; j < oldList.size; j++)
{
//compare oldList.get(i) with oldList.get(j)
//if match, set some boolean
}
//if duplicate found, delete one copy, or add one to new list, etc
}
This allows you to go through each element in the outer loop, and compare to every other element in the inner loop.
I guess employee id (empid) is unique for each emplyee, yes?
If so, use a hash instead where empid is the key and employee object is the value.
Map<Long, Employee> empmap = new HashMap<Long, Employee>();
empmap.put(currentEmployee.getEmpid(), currentEmployee)

Categories