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);
Related
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.
I am trying to make two dimensional hashset functionality. I have a loop that iterates through pairs of integers:
ResultSet getAssociations;
Statement getAssociationsSelect = sqlConn
.createStatement();
getAssociations = getAssociationsSelect
.executeQuery("SELECT ProductId, ThemeId FROM ProductTheme");
while(getAssociations.next()) {
int productId1 = getAssociations.getInt(1);
int themeId1 = getAssociations.getInt(2);
}
When the current pair of integers does not match a previous pair of integers I want to store them. I figured a hashset would be the best approach because I can insert the pairs and it wont take repeats. How do I do this?
I think you might be over-thinking the problem a bit. I would suggest the following:
Map<Integer, Set<Integer>> map = new HashMap<Integer, Set<Integer>>();
if(!map.containsKey(productId))
map.put(productId, new HashSet<Integer>());
map.get(productId).add(themeId);
This way you have a Set of all the themeIds that map to a given productId, guaranteeing uniqueness while creating an object with an easily iterable format.
Create a new object which can act as a composite key based on productId1 and themeId1. Make sure and implement the equals and hashCode methods and store these objects in the Set.
public class AssociationReference() {
private int productId;
private int themeId;
//constructor/getters/setters
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + productId;
result = prime * result + themeId;
return result;
}
public boolean equals(Object obj) {
}
}
Now you can use HashSet and only unique values will be stored. You can also use this Object as the Key on a HashMap if you need to store more.
I would avoid creating a key by conjoining values unless you are sure that the ranges will never change, and that you ca careful to pad your numbers so there can be no collision (i.e 9 and 11 should be 00090011 rather than 911 so as to be distinguishable from 91 and 1).
If you want a really simple solution concatenate both keys and store the resulting string, e.g.
String newKey = String.format( "%d-%d.", productId1 , themeId1 );
It will allways generate a unique key for each combination.
I would use a HashMap<Long, Association>
As Keys i would use ProductId * 1000000 + ThemeId so they look like this:
32000064 for ProductId = 32 and ThemeId = 64
be sure to implement equals and hashcodein your Association class
Im a beginner in Java. I have 3 ArrayLists and all of the ArrayLists contain data pertaining to a specific subject and hence have the same length. I want to iterate through the array and perform some operations as illustrated below:
public void example(){
ArrayList<Long> ID = new ArrayList<Long>;
ArrayList<Integer> AcNo = new ArrayList<Integer>;
ArrayList<Integer> Vnum = new ArrayList<Integer>;
//get ID and AcNo from user, compare it in the ArrayList, get the corresponding Vnum
// for the Vnum from previous step, compare it with the next Vnum and get corresponding ID and AcNo until some *condition* is satisfied.
}
How do I do this in Java? I saw examples of Iterator, but Im not sure about the correct method to do this! Please help.
If all three lists are of the same length, then iterate over them using for loop with indexes. Same indexes represents the same user in each of the three lists:
for (int i=0; i<ID.size(); i++) {
Long userId= ID.get(i);
Integer userAcNo= AcNo.get(i);
Integer userVnum= Vnum.get(i);
//if the next user exist, get the next user
if (i + 1 < ID.size()) {
Long nextUserId= ID.get(i+1);
Integer nextUserAcNo= AcNo.get(i+1);
Integer nextUserVnum= Vnum.get(i+1);
//now compare userVariables and nextUser variables
}
}
A better approach would be to have a single list of Subject objects or similar, so that each Subject contains all relevant data about itself.
class Subject {
private final long id;
private final int acNo;
private final int vnum;
/* Appropriate constructor and getters... */
}
You might also want to consider renaming the fields so that they are more descriptive.
I have an object, named objectOne, which each of its row contain 3 variables (String var1, String var2, int var3). So for each row, the data should be var1;var2;var3
My question is how to count frequency based on its object and its variable-in-object ? because code like int occurrences = Collections.frequency(list, item); cannot get its occurrences for a specific variable-in-object.
For example i have
objectOne :
is;is;125
that;is;861
you;are;90
that;is;469
I want to get how many occurrence of is word in var2 column (which the answer should be 3) and how many occurrence of that word in var1 column (which the answer should be 2) ?
Any help will be appreciated :)
I would implement the logic for finding the frequency by myself in the class as no direct API that exists for this purpose from existing Collection framework.
public int findOccurances(Collection list, String column,String item) {
int count = 0;
ObjectOne myObj;
String value="";
Iterator itr = list.iterator();
while(itr.hasNext()) {
myObj = (ObjectOne)itr.next();
if(column.equalsIgnoreCase("col1")) value = myObj.getCol1();
if(column.equalsIgnoreCase("col2")) value = myObj.getCol2();
if(value.equalsIgnoreCase(item)) {
count++;
}
}
return count;
}
Hope this would help and throw some light to improve much better.
Wrap the data elements in nodes that have count and value. On insertion, either create a new one if none exists and set the count to 1, or increment count if it's already there. The node count will then only need to be examined instead of calculated.
I need to create an Arraylist in a while loop with a name based on variables also in the loop. Here's what I have:
while(myScanner.hasNextInt()){
int truster = myScanner.nextInt();
int trustee = myScanner.nextInt();
int i = 1;
String j = Integer.toString(i);
String listname = truster + j;
if(listname.isEmpty()) {
ArrayList listname = new ArrayList();
} else {}
listname.add(truster);
i++;
}
The variable truster will show up more than once while being scanned, so the if statement is attempting to check if the arraylist already exists. I think I might have done that out of order, though.
Thanks for your help!
Store the ArrayLists in a Map:
Map<String, List<String> listMap = new HashMap<String,List<String>>();
while (myScanner.hasNextInt()){
// Stuff
List<String> list = new ArrayList<String>();
list.add(truster);
listMap.put(listname, list);
}
Note the use of generics (the bits in <>) to define the type of Object the List and Map can contain.
You can access the values stored in the Map using listMap.get(listname);
If I understand you correctly, create a list of lists or, better yet, create a map in which the key is the dynamic name you want and the value is the newly created list. Wrap this in another method and call it like createNewList("name").
Really not sure what you mean at all but you have some serious fundamental flaws with your code so I'll address those.
//We can define variables outside a while loop
//and use those inside the loop so lets do that
Map trusterMap = new HashMap<String,ArrayList<String>>();
//i is not a "good" variable name,
//since it doesn't explain it's purpose
Int count = 0;
while(myScanner.hasNextInt()) {
//Get the truster and trustee
Int truster = myScanner.nextInt();
Int trustee = myScanner.nextInt();
//Originally you had:
// String listname = truster + i;
//I assume you meant something else here
//since the listname variable is already used
//Add the truster concated with the count to the array
//Note: when using + if the left element is a string
//then the right element will get autoboxed to a string
//Having read your comments using a HashMap is the best way to do this.
ArrayList<String> listname = new ArrayList<String>();
listname.add(truster);
trusterMap.put(truster + count, listname);
i++;
}
Further, you are storing in myScanner a stream of Ints that will get fed in to the array, but which each have very different meanings (truster and trustee). Are you trying to read these in from a file, or user input? There are better ways of handling this and if you comment below with what you mean I'll update with a suggested solution.