How to compare a fixed java array and a dynamic one? - java

I am developing a tuition management system that is focused on adding subjects for the tuition . It is more focused for the tuition staff. I have set a fixed array of students which is around 20 and I want to compare that array with a dynamic list of subjects array to get the number of students under a particular teacher.
Unfortunately both arrays obviously has different sizes so how do I loop through it?
public void checknumberofstudents()
{
for (int i = 0; i < ChooseStudent.suboptions.size(); i++)
{
System.out.println(data.get(i).collectionz.size());
if (data.get(i).collectionz.get(i).getTeacher() == ChooseStudent.suboptions.get(i).getTeacher())
noofteachers[i]++;
else
{
System.out.println("Error with the teacher array");
}
}
}
data is a fixed list of students.Each student has their own collection
of subjects.So i get the index of a particular student then get a
particular subject under his/her collection then get the teacher name
so I can match it with the dynamically allocted subjects arrray's
teachers. Then I will update the noofteachers array so I can get the
number of students under a particular teacher.
It is a big project with a lot of code so I don't think so it's appropriate to share it here. Here is a link to my github for the whole project.
https://github.com/ariff20/UPSR

Based on your code, the following code should work
public Map<String, Integer> studentsByTeacherCount(ObservableList<Student> data) {
Map<String, Integer> teacherMap = new HashMap<String, Integer>();
for (int i = 0; i < data.size(); i++) {
Student student = data.get(i);
List<Subject> subjectList = student.getCollectionz();
for(Subject subject: subjectList) {
Integer entry = teacherMap.get(subject.getTeacher());
if(entry == null) {
teacherMap.put(subject.getTeacher(), Integer.valueOf(1));
} else {
teacherMap.put(subject.getTeacher(), entry + 1);
}
}
}
return teacherMap;
}

Make your comparison code independent of the array sizes.
In other words, map the occurrence of elements inside the smaller array to their occurrence in the bigger one, traversing both entirely and independently of each-other.
When you have the map, you can know whether all elements of the smaller array are found within the bigger array, and, in reverse, even which elements the bigger array has, and the smaller one doesn't.

Related

Removing duplicates from an ArrayList?

Good afternoon everyone, I am currently studying for my Java Final and I have a review exercise that asks the reader to create a program that asks the user to input 10 integers and then to use a method to remove duplicates and display the distinct list. The method is provided for you as well.
I've gotten the majority of the code written, in fact I thought I was done until I realized that the for loop is removing more than just duplicates..
Here is my code:
public class lab25 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int i;
//Create array list
ArrayList<Integer> numbers = new ArrayList<>();
System.out.println("Please enter 10 numbers!");
//Populate
for(i=0; i<10; i++) {
numbers.add(input.nextInt());
}
System.out.println("Your numbers are: " + numbers.toString());
removeDuplicate(numbers);
System.out.println("The distinct numbers are: " +numbers.toString());
input.close();
}
public static void removeDuplicate(ArrayList<Integer> list) {
int i;
for(i=0; i<list.size(); i++) {
if(list.contains(list.get(i))) {
list.remove(i);
}
}
}
}
Just curious what I have done wrong here? I think my issue might lie in my for loop.. Thanks to all who answer.
list.contains(list.get(i)) always returns true, since the i'th element of the List is contained in the List.
Therefore removeDuplicate is trying to remove all the elements (but you only remove half of them, since after removing the i'th element you skip the new i'th element).
There are many ways to remove duplicates. The most efficient involve using a HashSet. If you want to find duplicates using only List methods, you can check if list.lastIndexOf(list.get(i)) > i.
The expression list.contains(list.get(i)) is always true, since you're asking if the list contains some element from the list. You need to check if list.get(i) is contained in the first i-1 items in the list, which I recommend doing with a loop.
Be aware that a loop with list.remove will run slowly, since removing item i from an ArrayList is done by replacing item i with i+1, then replacing item i+1 with i+2 and so on. This means it takes around length^2 time to make a loop that calls remove in every iteration. The function list.contains has the same problem, as it has to go through the entire list. This may not matter if you have 10 items, but if you had a list with a million items, it would take a long time to run.
The easiest ways is to use Stream.distinct():
public static List<Integer> removeDuplicate(List<Integer> list) {
return list.stream().distinct().collect(Collectors.toList());
}
In case you are free to choose collection, you should use LinkedHashSet instead. It holds ordered unique numbers.
A solution could be this one. I startet at the end of the list that I don't delete indexes the loop has to visit in the future.
public static void removeDuplicate(ArrayList<Integer> list) {
int i = list.size() - 1;
while (i > -1) {
// check for duplicate
for (int j = 0; j < i; j++) {
if (list.get(i) == list.get(j)) {
// is duplicate: remove
list.remove(i);
break;
}
}
i--;
}
}
You are taking the list.get(i) which of course is present in the list, and you will delete all of the values in the end.
You could remove them by using a set:
Set<String> hs = new HashSet<>();
hs.addAll(numbers);
numbers.clear();
numbers.addAll(hs);
If you want to keep the current order and do not want to use set.
List<String> notduplicatedList =
new ArrayList<>(new LinkedHashSet<>(String));

compare two arraylist object not working

I have two array list with name list and sum from this kind of class :
public class Factor {
private String cat;
private String kind;
private String name;
private int number;
private String id;
}
my purpose is compare this two arraylist and if they have same object , list number = sum number else sum object add to list .
this is my try so far :
int size=list.size();
for (int j=0; j<size ;j++){
for (int i = 0; i < sum.size(); i++) {
if (list.get(j).getId().equals(sum.get(i).getId())){
list.get(i).setNumber(sum.get(i).getNumber());
} else {
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(),sum.get(i).getKind(), sum.get(i).getName(), sum.get(i).getNumber()));
}
}
}
but problem is always two condition run any way it mean do below in if list.get(i).setNumber(sum.get(i).getNumber());
and after that do below in else
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(), sum.get(i).getKind(),
sum.get(i).getName(), sum.get(i).getNumber()));
always add list ... so where am i wrong ?
Your logic was incorrect.
Based on the comments, you want to add to list all the elements of sum that don't have a matching ID in list. For that purpose you should iterate over the elements of sum first (i.e. in the outer loop).
int size=list.size();
for (int i = 0; i < sum.size(); i++) {
boolean found = false;
for (int j=0; j<size ;j++) {
if (list.get(j).getId().equals(sum.get(i).getId())) {
list.get(j).setNumber(sum.get(i).getNumber());
found = true;
break;
}
}
if (!found) {
list.add(new Factor(sum.get(i).getId(),sum.get(i).getCat(), sum.get(i).getKind(),
sum.get(i).getName(), sum.get(i).getNumber()));
}
}
you need to make sure both list size is the same, so if they are not the same size they wont be equal
Also this is a bad practice to compare two lists, a better way would be using a Set, just convert one of the lists to a set ( time complexity O(n) ) then loop over the other list and check if all elements are in the set you created from the other list, also you need to take care of duplicate case , so if duplicate is allowed in the list you need to use a map , where the id is the key and the value is the number of occurrences , while iterating over the other list if the key is found decrement the number and check if its not getting less than zero.
From your question, it's still not clear what you are trying to achieve from this code. Do you wanna compare every element of list array with every element of sum array or u just want to compare list array with the corresponding element of sum array.
As per my understanding,
From your code, I can see that u are using nested loos.
***for (int j=0; j<size ;j++)
{
for (int i = 0; i < sum.size(); i++) {}}***
So for every list(j) array, it will compare this all the elements of sum(i) array and out which some will execute IF block and some will execute else block depending upon the condition.
If this is not what u are looking for they give some more clarity on ur question.

How to access and modify elements of an int array within a Tree Map

So I'm doing a Star Trek themed project where I need to take a list of crew members and the planets they've visited and generate a log report for Starfleet.
For example this...
Guinan,Drema IV
Picard,Gamalon V
Barclay,Valo III
Riker,Theydat IV
Pulaski,Alpha Moon
Troi,Tessen III
...
Needs to become this
Acamar III:
B. Crusher 11
Barclay 6
Data 15
Gomez 3
Guinan 4
Lefler 5
O'Brien 12
Ogawa 4
Picard 5
Pulaski 14
Riker 12
Troi 9
W. Crusher 4
Worf 14
Yar 3
...
To do this I need to use a generic structure that automatically sorts the incoming data so I decided to use a Tree Map of 15-element int arrays to store the number of visits each crew member has made to a given planet.
My question is, since I am very new to Java, how would I get a value from an array element inside the tree map and update the value inside a given array element? My problem is that all the examples I can find about working with Tree Map either don't involve arrays inside of them or don't show how to get a value and update values after the first insertion. Below I've given my current psuedocode with my best guess as to how to accomplish this. If anyone knows of a way to do this, or a better method entirely please suggest it.
P.S. I'm going to implement the loop I need after I can get a single iteration written correctly
EDIT: For clarity, each element of the 15-element int array corresponds to a crew member so for example Data would be array[2] and Yar would be array[14]
import java.util.*;
public class TreeMapDemo {
public static void main(String args[]) {
// Create a hash map
TreeMap tm = new TreeMap();
int indexDesired;
int visits;
String planetNameVariable;
String crewMemberName;
//Scan input using Scanner and assign planet name and crew name to
//correct variables (code provided by instructor)
// Put elements to the map
//if(planet doesn't already exist in tm)
tm.put(planetNameVariable, new int[14]);
//Decides which element of the array must be incremented
indexDesired = crewToIndex(crewMemberName);
//Increments visit count of crewMemberName on planetNameVariable
visits = //How do I get the value of the array associated with planetNameVariable at indexDesired?
tm.put(planetNameVariable, int[indexDesired] = visits + 1 //How do I insert into an array element here?);
// Get an iterator
Iterator i = set.iterator();
// Display element
// Code not designed yet
}
}
You can something like this. Here you have to put array in map only once because after that you will get only reference so if you modify that it will be modified in map as well.[shallow copy]
int visits[] = null;
// Increments visit count of crewMemberName on planetNameVariable
visits = tm.get(planetNameVariable);
if (visits == null) {
tm.put(planetNameVariable, new int[14]);
visits = tm.get(planetNameVariable);
}
visits[indexDesired]++;
// Get an iterator
Iterator<String> iterator = tm.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
int[] temp = tm.get(key);
if (temp != null) {
for (int i = 0; i < temp.length; i++) {
System.out.println(key + " " + temp[i]);
}
}
}

ensuring all the ids value in the hashMap are different?

The method below (generateID())it generate a random ids, And when i store students in the HashMap i want to check if the generated id is not exist in the hashMap value and if its exists I want to generate a new id and then store it, The problem with the method store sometimes it does not store all the student because some student might have the same id and this is not allowed, So what is the best why to check that all ids are uniqe and if there is duplication the method generateid will be called again util all the ids are uniqe and then it will store it, I want to ensure that the ids values produced by generateId() are all different
private String generateId(String perfix, int numberaOfDigits)
{
for(int i=0;i<numberaOfDigits;i++)
{
perfix += randomGenerator.nextInt(9)+ 1;
}
return perfix;
}
public void store(Student student)
{
int index = 0;
studentMap.setId(generateId("AB-",1));
while(index <= studentMap.size())
{
for(Student stu : studentMap.values() )
{
if(student.getStduentID().equals(stu.getStduentID()))
{
student.setId(generateId("AB-",1));
}
}
index++;
}
}
studentMap.put(student.getStduentID(),student);
}
you can use the containsKey() method to check if an ID is already in use as key
Use an UUID. Or a sequence as already answered
If that's actually a Map implementation, you should be able to use .containsKey(). The problem is that, depending on how well written your ID generator is, this can cause significant performance issues over time. Say you have a 6 digit ID, and in a few years 80000 students have passed through the system. How many guesses will it need before it finds one of the remaining 20000 available keys?
You can get from the map with the generated Id, if it returns null, then it doesn't exist
yet.
Map<Long, Object> myMap = new HashMap<Long, Object>();
Long id = generateRandomId()
Object value = getMyObjectValue();
while(myMap.get(id) != null){
id = generateRandomId();
}
myMap.put(id, value);
I would eliminate the generateId() method altogether, and simply do this:
private int id;
then:
student.setId(id++);
I suggest to try following implementation to get unique random number each time.
Add items to the list .
Use Collections.shuffle(list); to shuffle the list .
Iterate over list and get random number each time from the given range. (For below case range is from 0 to numberOfStudent-1).
int numberOfStudent = 10;
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < numberOfStudent; i++)
list.add(i);
Collections.shuffle(list);

Returning two object from a function without an ArrayList

I'm not sure how to word this correctly, but I'm told to write a method that would return the largest course object (the course with the most students). If there are two courses that have the same number of students, it would return both.
The second part of the problem is what troubles me, because I'm not allowed to make another ArrayList other than the ones he specified (which is already used). Is there a way to keep track of two+ objects without using an list/hash?
This is what I've done so far, but it only returns one course object.
public Course largestEnrollment(){
int size = 0;
Course p = null;
for (Integer c : courseList.keySet()){
if (courseList.get(c).getClassList().size() > size){
p = courseList.get(c);
size = courseList.get(c).getClassList().size();
}
return p;
}
return null;
}
Return an array of Course objects:
public Course[] largestEnrollment(){
You'll need to decide how to manipulate the array inside your for loop.
Sort the ArrayList based on size. Then you can return a sub-list of the largest courses.
If you don't have so many Course (e.g. <1k), you could implement Comparable or write a Comparator for your Course object. So that you could just from the map get all Values(Course) in collection, then sort the collection, just from the end of the sorted collection take those elements with same values(size).
I mentioned the size of the collection because sort make the O(n) problem into O(nlogn). But if the size is small, it is a convenient way to go.
Anyway, you have to change the method return type to a collection or an array.
Sort then return a sublist:
public List<Course> largestEnrollment(List<Course> courses) {
Collections.sort(courses, new Comparator<Course>() {
#Override
public int compare(Course o1, Course o2) {
return o1.getClassList().size() - o2.getClassList().size();
}
});
for (int indexOfLargest = 1; indexOfLargest < courses.size(); indexOfLargest ++) {
if (courses.get(indexOfLargest - 1).getClassList().size() > courses.get(indexOfLargest).getClassList().size())
return courses.subList(0, indexOfLargest);
}
return courses;
}

Categories