I'm trying to write a program that handles the storing of students and corresponding subjects, but am relatively new to Java's Lists and am having trouble getting the class to store and output the students and subjects. So far I can get it to store a student and class but will not take multiple, or only returns the most recent one added.
private static Map<String, Set<String>> cohort = new HashMap<~>();
public static void signOn(String class, String student) {
Set<String> studentSet = new HashSet<String>();
studentSet.add(student);
cohort.put(class, studentSet);
}
public static Map<String, Set<String>> getCohort() {
return cohort;
}
When calling getCohort() I am trying to get it to return all students that have signed on, but it is only returning the most recent student added in. I'm not sure if I am missing something simple but I just can't seem to get it right, any help would be very appreciated.
in signOn when you are adding a new student, you are creating a new Set, adding one student to it and then overrides any Set that was already there. This means that you will always only have one student there.
What you need to do is to first get the current set of students in a class, and then add your student to them.
Example code:
public static void signOn(String class, String student)
{
Set<String> studentSet = cohort.get(class);
if (studentSet == null) {
studentSet = new HashSet<String>();
cohort.put(class, studentSet);
}
studentSet.add(student);
}
That should work as studentSet will be a reference to the studentSet that is stored in cohort. I just wrote that from memory so no promises it works in the first try, but that is the general idea.
You are always creating a new Set, thus overriding the already existing set you saved in cohort.
Try the following:
Set<String> studentSet = cohort.get(class);
if(studentSet == null){
studentSet = new HashSet<String>();
cohort.put(class, studentSet);
}
studentSet.add(student);
As a side note I would like to add that 'class' is properly not the best name for your String variable as it's a Java reserved word.
You are facing the problem as you are putting new Set every time (also when student class is the same), which basically override the old value. So, you need to put a student in the same set if the class is the same. Using Java 8 you can do as follows :-
public static void signOn(String cls, String student) {
cohort.computeIfAbsent(cls, k -> {
Set<String> studentSet = new HashSet<>();
studentSet.add(student);
return set;
});
cohort.computeIfPresent(cls, (k, v) -> {
v.add(student);
return v;
});
}
Note: You can't have a variable name class, it is a reserved keyword in java.
Related
I am wondering how to build a nested Map and then retrieve the nested key:value pairs. This is how I created the map to be nested.
//Create List of Nested HashMaps
List<Map> nestedMap = new ArrayList<>();
nestedMap.add(building3Map);
nestedMap.add(building31Map);
nestedMap.add(buildingHFTFMap);
System.out.println("The nested map is: " + nestedMap);
This is the system output for the following code:
The nested map is: [{buildingname=[Building 3], buildingid=[3]}, {buildingname=[Building 31], buildingid=[1]}, {buildingname=[HFTF], buildingid=[4]}]
This is correct as I want a list of maps. But the next step is what is confusing to me. When I try to build the outer layer Map as below:
HashMap<String, List<Map>> queryMap = new HashMap<>();
queryMap.put("buildings", nestedMap);
System.out.println(queryMap.get("buildings.buildingid"));
I get a system output of null when attempting the .get("buildings.buildingid") method. Ideally, I need the output to look like this:
[[3, 1, 4]]
Where it returns all values with a key of "buildings.buildingid" in an array. I am new to coding so please let me know if I'm making any fundamental errors and how I can create a nested Map where I can access the inner layer or if there is another method I should be using.
I think you are making it way too complicated than it should be. you can store your data in a simple map where the ids are the keys for example and the names are the values. So you only need to read the keys or the values from the map to get your result.
Map<Integer, String> myMap = new HashMap<>();
myMap.put(3, "Building 3");
myMap.put(31, "Building 31");
myMap.put(4, "HFTF");
System.out.println(myMap.keySet());
System.out.println(myMap.values());
However, Java is an object-oriented language. If it makes sense for your use case you might want to create a custom class "Building" instead of frantically trying to store your data in nested data structures. See below for an example of how it might look using a custom class:
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String args[]) {
List<Building> buildings = new ArrayList<>();
buildings.add(new Building(3, "Building 3"));
buildings.add(new Building(31, "Building 31"));
buildings.add(new Building(4, "HFTF"));
List<Integer> buildingIds = new ArrayList<>();
buildings.forEach(building -> buildingIds.add(building.getBuildingId()));
List<String> buildingNames = new ArrayList<>();
buildings.forEach(building -> buildingNames.add(building.getBuildingName()));
System.out.println(buildingIds);
System.out.println(buildingNames);
}
public static class Building {
int buildingId;
String buildingName;
public Building(final int buildingId, final String buildingName) {
this.buildingId = buildingId;
this.buildingName = buildingName;
}
public int getBuildingId() {
return buildingId;
}
public void setBuildingId(final int buildingId) {
this.buildingId = buildingId;
}
public String getBuildingName() {
return buildingName;
}
public void setBuildingName(final String buildingName) {
this.buildingName = buildingName;
}
}
}
queryMap.get("buildings.buildingid") returns null, because queryMap only contains a value under the key
buildings. A HashMap can only access the value using the same key it was stored under. The key and the value is not processed in any further way.
A simple alternative could be
queryMap.get("buildings").stream() // Create a Stream<Map>
.map(building -> building.get("buildingid")) // Create Stream<String> by extracting the buildingid values.
.collect(Collectors.toList()); // Collect Stream into a List<String> which contains the buildingid's
If you don't like this solution you could take a deeper look into property expressions, and write your own map implementation that can resolve these expressions. But it will be a lot of work to get it working correctly...
I am having array list let's consider it for users . Each user object has a variable called id I tried to use contains methods with the same object exactly but I surprised that it isn't working.. How can I know if the list contains a user with an id that I am looking for without looping on the list elements? I know that I can use loop but I am looking for a better way to do that
Contains in array list is always linear complexity meaning that it always loops through the elements. If you want your contains to work the way you intended you could override equals and make it use the id field in User class. Another way to solve this problem would be to not use array list but HashMap with your ID as a key and a user as value or maybe even a HashSet as it always uses equals before adding elements to the collection.
public class UserList extends ArrayList<User> {
#Override
public boolean contains(Object o) {
Object[] arr = this.toArray();
for (Object obj:arr) {
if(obj.toString().equals(String.valueOf(o))){
return true;
}
}
return false;
}}
class User {
String id;
String name;
#Override
public String toString() {
return id;
}
}
If you did not override equals in your User class, it will check if it is the same instance, not if the field values are equals.
If you don't want to override equals, using only the id, you can keep the users in a
Map<String,User> users; => users.containsKey(id)
where the key is the id, or keep just the ids in a separate
Set<String> ids; and call contains. => ids.contains(id)
As you mentioned, it is possible to iterate the array list to get the answer. If you do not want to do it, you can just copy the values into a hash map like:
Map<String, User> userMap = new HashMap();
for (int i=0; i<arrayList.size(); i++) {
userMap.put(arrayList.get(i).getId(), arrayList.get(i));
}
String isExist = userMap.containsKey(id);
Lets say you want to select user with id=23, using stream,
List<User> usersLlist = New LinkedList<>();
User user;
user = usersLlist.stream().filter( user -> user.id == 23).findAny();
if you are using a get method to get user id
user = usersLlist.stream().filter( user -> user.getId() == 23).findAny();
Hey I am implementing this function.
private static HashMap<String, Set<String>> enrollments = new HashMap<String, Set<String>>();
private static Set<String> studentset;
/**
* Enrolls a student into a unit.
*
* #param unit
* #param student
*/
public static void enroll(String unit, String student) {
if(!enrollments.containsKey(unit)) {
studentset = new HashSet<String>();
}
studentset.add(student);
enrollments.put(unit, studentset);
}
/**
* Gets a list of all students of a particular discipline. E.g. If discipline is
* "ABC" then return a collection of all students enrolled in units that start
* with "ABC", so ABC301, ABC299, ABC741 etc. This method is non-trivial so it
* would help to first implement the helper method matchesDiscipline (below).
*
* #param discipline
* #return
*/
public static Set<String> getStudents(String discipline) {
Set<String> myList = new HashSet<String>();
for (Entry<String, Set<String>> e : enrollments.entrySet()) {
if (e.getKey().startsWith(discipline)) {
myList.addAll(e.getValue());
}
}
return myList;
}
public static void main(String[] args) {
EnrollmentManager.enroll("CAB302", "James");
EnrollmentManager.enroll("CAB403", "Ben");
EnrollmentManager.enroll("CAB302", "James");
EnrollmentManager.enroll("CAB403", "Morgan");
EnrollmentManager.enroll("CAB404", "Sam");
System.out.println(EnrollmentManager.getStudents("CAB3"));
}
The problem im having is 'myList' is outputting [Morgan, James, Ben]. Where the correct answer would be [James]. Where am I going wrong? Sorry if its a simple solution im new to Collections.
The problem with your code is that you are using a static studentSet variable. Let me dry run your code.
What you are doing here is that you are creating a new set when key is not found, otherwise you are using existing set, which is your static member.
if(!enrollments.containsKey(unit)) {
studentset = new HashSet<String>();
}
EnrollmentManager.enroll("CAB302", "James"); will create a new set, let's say set1 and assign it to static member studentset. studentset after this step {James}.
EnrollmentManager.enroll("CAB403", "Ben"); will create a new set, let's say set2 and assign it to static member studentset. studentset after this step {Ben}
EnrollmentManager.enroll("CAB302", "James"); will NOT create a new set and use current value of studentset i.e. set2. studentset after this step {Ben,James}
EnrollmentManager.enroll("CAB403", "Morgan"); will NOT create a new set and use current value of studentset i.e. set2. studentset after this step {Ben,James,Morgan}.
And since your map has a reference to this static member, whenever you retrieve , you are getting the static member values..
What you should do is instead of using the static set member, you can use a function variable.
And change your condition like this:
Hashset<String> studentset = null;
if(!enrollments.containsKey(unit)) {
studentset = new HashSet<String>();
}else{
studentset = enrollments.containsKey(unit);
}
You can change your enroll method like below to work:
public static void enroll(String unit, String student) {
if(!enrollments.containsKey(unit)) {
studentset = new HashSet<String>();
enrollments.put(unit, studentset);
} else {
studentset = enrollments.get(unit);
}
studentset.add(student);
}
Your mistake: you have a static reference private static Set<String> studentset; which in your case is used to add a new student in the previous entry of map when !enrollments.containsKey(unit) returns false. Best practice is to make this a local variable and define it in enroll method.
Problem is with your static variable studentset and you are adding to that set even if there is studentset already in the map for a unit. You should add to the already existing set in the map if a key is found.
If you are using Java 8 or higher you can simply do it in one line :
enrollments.computeIfAbsent(unit, k -> new HashSet<>()).add(student);
And you don't need a studentset static field at all.
I am struggling with following:
I need to create a method which returns a collection of all values that specify some particular selection criterion specified by one or more arguments.
My MAP consists of PPS numbers(keys) and values( town, name, surname, place of work ) Both are strings .
However, I am not sure what I need to do to get the values after placin in the map.
/**
*This method returns a collection of all people who work for CO-OP
*/
public Set<String> selectKeys(String factory)
{
for (Set<String>eachTaxPayers : taxPayersList.values())
{
if(taxPayersList.values().contains(factory))
{
Set<String>eachClients = taxPayersList.keySet();
System.out.println(taxPayersList.keySet());
}
}
return null ;
}
Could someone help me please?
This is a code how Map is populated.
public class Tax
{
Map<String, Set<String>>taxPayersList;
public Tax()
{
taxPayersList = new HashMap<>();
Set<String>taxPayersDetails = new HashSet<>();
taxPayersDetails.add(" Eddie Donegan");
taxPayersDetails.add("Prodieco");
taxPayersDetails.add("Limerick");
taxPayersList.put("4481908A", taxPayersDetails);
taxPayersDetails = new HashSet<>();
taxPayersDetails.add(" Paddy Power");
taxPayersDetails.add("Covenant");
taxPayersDetails.add("Limerick");
taxPayersList.put("6088989B", taxPayersDetails);
taxPayersDetails = new HashSet<>();
taxPayersDetails.add(" Mikey Obama");
taxPayersDetails.add("Prodieco");
taxPayersDetails.add("Limerick");
taxPayersList.put("6788910B", taxPayersDetails);
}
}
I want only to return the key's( PPS numbers) for people who works for the same company
public Set<String> selectKeys(String factory) {
// our return Set
Set<String> factoryWorkers = new HashSet<>();
// Let's iterate over the map entries
for (Map.Entry entry : taxPayersList.entrySet()) {
// Let's grab the value of the current map entruy
Set<String> eachTaxPayers = entry.getValue()
// Risky move
if(eachTaxPayers.contains(factory)) {
// add the key (PPS) to the return set
factoryWorkers.add(entry.getKey());
}
}
return factoryWorkers;
}
FYI, the line marked as "Risky Move" is not the best approach.
Though unlikely, it's possible a city has the same name as factory.
You'd be better using an Iterator on the Set and comparing against the 2nd value.
Even better, instead of having a Map>
you could have a Map
where Employee has fields such as name, city and factoryName.
I am trying to find a way to store a new instance of a class as the value in a Java hashmap. The idea was given to me by a Java instructor in order to create a data storage structure that could be used to for a program I am working on.
The idea he recommended to me was to use a hashmap that stored the name of a computer as the key and the value would be a new instance of the class InfoStor.class. InfoStor contains methods such as getName(), setName(), getMemory()...
I have the class and the method pretty much setup for a basic test to see if it would work or not. The problem I am running into is I cannot figure out how to use the methods inside of InfoStor once I have created a new entry in the hashmap.
This is the code I have so far;
VMware.class
import java.util.HashMap;
public class VMware {
public static void main(String[] args) {
HashMap <String, Object> mapper = new HashMap();
mapper.put("NS01", new InfoStor("NS01"));
//mapper.get("NS01").
}
}
InfoStor.class
public class InfoStor {
private String vmName;
private String platform;
private Integer memory;
public InfoStor (String name) {
vmName = name;
}
String getName(){
return vmName;
}
void setPlatform(String p){
platform = p;
}
String getPlatform(){
return platform;
}
void setMemory(Integer m){
memory = m;
}
Integer getMemory(){
return memory;
}
}
What I am trying to accomplish is something like this (basic idea).
Object var = mapper.get("NS01");
System.out.println(var.getMemory());
Am I going about this the wrong way? Any help is appreciated thanks.
The problem is that your code only specifies that the values in the map are Object. You know more than that, so tell the compiler that information:
HashMap<String, InfoStor> mapper = new HashMap<String, InfoStor>();
mapper.put("NS01", new InfoStor("NS01"));
...
InfoStor value = mapper.get("NS01");
Integer memory = value.getMemory();
Note that it's generally though not always better to use interfaces for the variable types - and you can use the diamond operator for the constructor call, letting the compiler use type inference to fill in the type arguments:
Map<String, InfoStor> mapper = new HashMap<>();
mapper.put("NS01", new InfoStor("NS01"));
...
InfoStor value = mapper.get("NS01");
Integer memory = value.getMemory();
If you declare your hashmap like so:
HashMap<String, InfoStor> mapper = new HashMap<String, InfoStor>();
Then when you get an object out of the mapper, it will be an instance of InfoStor (you won't need to cast it or worry about a class cast exception because it's not the rist class.)
So:
InfoStor myStor = mapper.get("somekey");
myStor.getMemory(); // this will work
Otherwise, if you stick with the HashMap<String, Object> you used in your original code, you'll need to cast it before you call the method:
Object obj = mapper.get("somekey");
((InfoStor)obj).getMemory(); // cast is required
obj.getMemory(); // this will not compile
You should read up on Java generics.
Make use of the generics added to java. They help with both compile-time type-checking and they make the casts unnecessary.
HashMap <String, Object> mapper = new HashMap();
//you will be able to retrieve an object and then cast it to your InfoStore
InforStore isN01 = (InfoStore)mapper.get("N01");
//this will unfortunately be accepted, even thought it's a bug
mapper.put("N02", new Integer(0));
________________________
HashMap <String, InfoStore> mapper = new HashMap();
//you will be able to retrieve an object and then cast it to your InfoStore
InforStore isN01 = mapper.get("N01"); //no cast
Youre on the right track...
Initialise the map as:
HashMap <String, InfoStor> mapper = new HashMap<String, InfoStor>();
Then after adding objects to the map retrieve them with:
InfoStor var = mapper.get("NS01");
System.out.println(var.getMemory());
you can cook something by using array...for example if you can store objects in arrays then use that idea to achieve it in hash map...i dont knw how you design but i once got stuck in that and made through like this
example...
class princess{
int age;
public princess(int age){
this.age=age;
}
public int getAge(){
return this.age;
}
}
public class hashmaptest {
public static void main(String[] args) {
princess[] p=new princess[10];
HashMap scores = new HashMap();
scores.put("a",new princess(6));
scores.put("b",new princess(7));
p[0]=(princess)scores.get("a");
System.out.println(p[0].getAge());
p[0]=null;
p[0]=(princess)scores.get("b");
System.out.println(p[0].getAge());
}
}