I want to create a HashMap that has a key of type String and a value of a List of Objects that is set up in another class.
The code I have tried works in that it adds a key and a value to the map, but wont add multiple values to 1 key. I.E I would like Key x to have values 1,2 and 3 but it just seems to overwrite the last value rather than add another one.
This is my current code:
public class LeagueAdmin {
private Map<String, List<Team>> teams;
/**
* Constructor for objects of class LeagueAdmin
*
*/
public LeagueAdmin() {
this.teams = new HashMap<>();
}
public void addTeam(String division, Team team) {
if(!this.teams.containsKey(division))
{
List<Team> Team = new ArrayList<>();
Team.add(team);
this.teams.put(division, Team);
} else {
List<Team> newTeam = this.teams.get(division);
}
}
}
As I said, when I add multiple values to the key string 'top' for example I expect 'top' to show me all the values added to it, instead it only shows the latest one added. Also as mentioned the Team object is handled in a separate class file.
Your else is incomplete. You make a list but never add to it when it sees that the key division exists. Add
newTeam.add(team);
to your else statement
Related
I've created a TreeMap with products.
And I want to count the number of times they repeat themselves, but have no clue what to code. Any hints? (I expect no code, just suggestions)
private static Map<Integer, String> shoppingCart() {
Map<Integer, String> result = new TreeMap<>();
result.put(1, "sausage");
result.put(2, "sausage");
result.put(3, "soup");
result.put(4, "egg");
result.put(5, "egg");
result.put(6, "tomato");
result.put(7, "sausage");
return result;
}
I was thinking about adding a counting variable, but still it doesn't fix the repeating problem.
Maybe not the best approach, but without modifying what you already have, you could use another map to store the products as keys and the quantity as the value for those keys:
Map<Integer, String> result = shoppingCart();
Map<String, Integer> productQuantities = new HashMap<>();
result.values().forEach(value ->
productQuantities.put(value,productQuantities.getOrDefault(value, 0) + 1));
To print the resulting map:
productQuantities.forEach((key, value) -> System.out.println(key + ":" + value));
I created a TreeMap with products, and i want to count the number of times they repeat themselves
Probably a different type of Map with keys representing items and values representing the corresponding count would be more handy. Something like:
NavigableMap<String, Integer> countByItem
Note: in order to access methods of the TreeMap like ceilingKey(), floorKey(), higherEntry(), lowerEntry(), etc. which are not defined in the Map interface you need to use NavigableMap as a type.
And it might make sense to make the item to be a custom object, instead of being a String. That would guard you from making typo, and it provides a possibility to gives useful behavior to Item
public class Item {
private int id;
private String name;
// constructor, getters, equals/hashCode, ect.
}
That's how map of items can be updated using Java 8 method merge(), which expects a key, a value and a function responsible for merging the old value and the new one:
NavigableMap<Item, Integer> countByItem = new TreeMap<>(Comparator.comparingInt(Item::getId));
countByItem.merge(new Item(1, "sausage"),1, Integer::sum);
countByItem.merge(new Item(1, "sausage"),1, Integer::sum);
countByItem.merge(new Item(2, "soup"),1, Integer::sum);
If you don't feel very comfortable with Java 8 functions, instead of merge() you can use combination of methods put() & getOrDefault():
Item sausage = new Item(1, "sausage");
countByItem.put(sausage, countByItem.getOrDefault(sausage, 0) + 1);
I can only guess at your goal. In your Map <Integer, String>, what does the Integer represent? Product number? Quantity? Sequence number? Something else?
If the Integer represents quantity, you have it backwards. It should be Map <String, Integer>. In a Map<X,Y>, the X represents the key. A Map allows fast lookup by the key. The Y is the value -- the information you want to find for a particular key, if the key is in the Map.
For example, if you want to add "sausage", you want to check if it is in the Map. If it isn't, put it into the Map with quantity 1. If it is, retrieve it and update the quantity.
If the Integer represents a sequence number (1st item, 2nd item, 3rd item, ...), you don't need a Map. Consider using an array or a data structure that preserves order, such as a List.
However, using an array or List still leaves you with the problem of how find how many of each item are in the list, when duplicates are allowed, as they are in your problem. To solve that, consider a Map<String, Integer> where the Integer (map value) is the quantity, and the String (map key) is the product name.
If I were doing this, I'd create classes to allow me to glue together related information. Here is part of a hypothetical example, which might be more realistic than you need:
public class Product {
private int upc; // product code, often represented with bar code
private Decimal price;
private String description;
private String shortDescription;
private ProductClass prodClass; // department, taxable, etc.
// etc. -- add needed fields, or remove irrelevant
// constructors, getters, setters,
Override .equals and .hashcode in Product. You use the UPC for those.
If you use implements Comparable<Product>, you have the possibility of using binary search, or a search tree.
public class Receipt {
private Decimal total;
private Decimal taxableTotal;
private Map <Product,Integer> shoppingCart; // Product, Quantity
// etc.
When each item is scanned, you can lookup the Product in the Map, and add it if not found, or update the quantity if found, as in the previous answers.
I have made various methods for someone to add a key which then includes various values from another created object.
I need to then allow a user to search using a method name which will then return all the people that match their search.
public Set findPerson(String aTrade)
{
Set<String> suitablePeople = new HashSet<>();
for (String test : this.contractors.keySet())
{
System.out.println(contractors.get(test));
if (contractors.containsValue(aTrade))
{
suitablePeople.add(test);
}
}
return suitablePeople;
}
I know this code is wrong but I'm just not sure how I can simply go through and find a value and return all the people that have this value within a range of values. For instance, their age, job, location.
Some assumptions, because your question is rather unclear:
contractors is a Map<String, ContractorData> field. Possibly ContractorData is some collection type (such as MyList<Contractor>), or named differently. The String represents a username.
aTrade is a string, and you want to search for it within the various ContractorData objects stored in your map. Then you want to return a collection of all username strings that are mapped to a ContractorData object that contains a trade that matches aTrade.
Whatever ContractorData might be, it has method containsValue(String) which returns true if the contractordata is considered a match. (If that was pseudocode and it's actually a List<String>, just .contains() would do the job. If it's something else you're going to have to elaborate in your question.
Then, there is no fast search available; maps allow you to do quick searches on their key (and not any particular property of their key, and not on their value or any particular property of their value). Thus, any search inherently implies you go through all the key/value mappings and check for each, individually, if it matches or not. If this is not an acceptable performance cost, you'd have to make another map, one that maps this property to something. This may have to be a multimap, and is considerably more complicated.
The performance cost is not important
Okay, then, just.. loop, but note that the .entrySet() gives you both key (which you'll need in case it's a match) and value (which you need to check if it matches), so that's considerably simpler.
var out = new ArrayList<String>();
for (var e : contracts.entrySet()) {
if (e.getValue().containsValue(aTrade)) out.add(e.getKey());
}
return out;
or if you prefer stream syntax:
return contracts.entrySet().stream()
.filter(e -> e.getValue().containsValue(aTrade))
.map(Map.Entry::getKey)
.toList();
The performance cost is important
Then it gets complicated. You'd need a single object that 'wraps' around at least two maps, and you need this because you want these maps to never go 'out of sync'. You need one map for each thing you want to have a find method for.
Thus, if you want a getTradesForUser(String username) as well as a findAllUsersWithTrade(String aTrade), you need two maps; one that maps users to trades, one that maps trades to users. In addition, you need the concept of a multimap: A map that maps one key to (potentially) more than one value.
You can use guava's MultiMaps (guava is a third party library with some useful stuff, such as multimaps), or, you roll your own, which is trivial:
given:
class ContractData {
private List<String> trades;
public boolean containsValue(String trade) {
return trades.contains(trade);
}
public List<String> getTrades() {
return trades;
}
}
then:
class TradesStore {
Map<String, ContractData> usersToTrades = new HashMap<>();
Map<String, List<String>> tradesToUsers = new HashMap<>();
public void put(String username, ContractData contract) {
usersToTrades.put(username, contract);
for (String trade : contract.getTrades()) {
tradesToUsers.computeIfAbsent(username, k -> new ArrayList<>()).add(username);
}
}
public Collection<String> getUsersForTrade(String trade) {
return tradesToUsers.getOrDefault(trade, List.of());
}
}
The getOrDefault method lets you specify a default value in case the trade isn't in the map. Thus, if you ask for 'get me all users which have trade [SOME_VALUE_NOBODY_IS_TRADING]', this returns an empty list (List.of() gives you an empty list), which is the right answer (null would be wrong - there IS an answer, and it is: Nobody. null is means: Unknown / irrelevant, and is therefore incorrect here).
The computeIfAbsent method just gets you the value associated with a key, but, if there is no such key/value mapping yet, you also give it the code required to make it. Here, we pass a function (k -> new ArrayList<>()) which says: just.. make a new arraylist first if I ask for a key that isn't yet in there, put it in the map, and then return that (k is the key, which we don't need to make the initial value).
Thus, computeIfAbsent and getOrDefault in combination make the concept of a multimap easy to write.
Assuming that your Map's values are instances of Contractor and the Contractor class has a Set<String> of trades (implied by the contains method call) and a getTrades() method that returns the list you could do it like this. Not certain what value the Map key would play in this.
get the values from the map and stream them.
filter only those Contractors that have the appropriate trade.
aggregate to a set of able contractors.
Set<Contractor> suitablePeople =
contractors.values()
.stream()
.filter(c->c.getTrades().contains(aTrade))
.collect(Collectors.toSet());
Note that a possible improvement would be to have a map like the following.
Map<String, Set<Contractors>> // where the key is the desired trade.
Then you could just get the Contractors with a single lookup up for each desired trade.
Set<Contractors> plumbers = mapByTrade.get("plumbers"); // all done.
Here is how you would set it up. The Contractor class is at the end. It takes a name and a variable array of trades.
Set<Contractor> contractors = Set.of(
new Contractor("Acme", "plumbing", "electrical", "masonry", "roofing", "carpet"),
new Contractor("Joe's plumbing", "plumbing"),
new Contractor("Smith", "HVAC", "electrical"),
new Contractor("Ace", "electrical"));
Then, iterate over the list of contractors to create the map. Then those are grouped by trade, and each contractor that matches is put in the associated set for that trade.
Map<String,Set<Contractor>> mapByTrade = new HashMap<>();
for (Contractor c : contractors) {
for (String trade : c.getTrades()) {
mapByTrade.computeIfAbsent(trade, v->new HashSet<>()).add(c);
}
}
And here it is in action.
Set<Contractor> plumbers = mapByTrade.get("plumbing");
System.out.println(plumbers);
System.out.println(mapByTrade.get("electrical"));
System.out.println(mapByTrade.get("HVAC"));
prints
[Acme, Joe's plumbing]
[Ace, Acme, Smith]
[Smith]
And here is the Contractor class.
class Contractor {
private Set<String> trades;
private String name;
#Override
public int hashCode() {
return name.hashCode();
}
#Override
public boolean equals(Object ob) {
if (ob == name) {
return true;
}
if (ob == null) {
return false;
}
if (ob instanceof Contractor) {
return ((Contractor)ob).name.equals(this.name);
}
return false;
}
public Contractor(String name, String...trades) {
this.name = name;
this.trades = new HashSet<>(Arrays.asList(trades));
}
public Set<String> getTrades() {
return trades;
}
#Override
public String toString() {
return name;
}
}
I'm trying to remove an element from a set that is in a map but I'm unsure how to do it.
The code I have so far is:
public void deleteToValue(String aLocation, String aEquipment)
{
locationMap.remove(aLocation, aEquipment);
}
The map key is the location and the the set is called equipment.
Assume the location is London and I want to remove a bike from the set.
The key and set will always be present so there's no need to check for nulls at this point.
This requires 2 steps:
Set<String> equipment = locationMap.get(aLocation) => returns the set
equipment.remove(aEquipment) ==> removes equipment from set.
If I understood you correctly, you have a map -> Map<String, Set<String>> and you want to remove equipment for some location.
Please, consider this code:
public void deleteToValue(String aLocation, String aEquipment)
{
Set<String> equip = locationMap.get(aLocation);
if (equip != null) {
equip.remove(aEquipment);
}
}
When calling map .get(..key..) method, it returns a value associated with a provided key, in your case, your value is Set<>.
So, to remove something from the set, firtly you need to read it from the map by key -> Set<String> equip = locationMap.get(aLocation); and then remove the required item from the Set -> equip.remove(aEquipment);
So I'm going crazy with this one. This is for an assignment and can't seem to get this to work at all!!
I have the following HashMap:
HashMap<String, ArrayList<Team>> teams;
(Team being another class to obtain the details of the teams)
What I need to be able to do is get the List of teams for the Key(String) from the above HashMap, and assign the List to a local variable I have declared:
List<Team> results = teams.get(division);
But this is where I get stuck. I have no idea how I'm suppose to complete this task.
As a further note "division" is the Key used in the HashMap. The ArrayList is a list of teams that belong to the division.
I have tried the below, which does not compile at all. Really not sure how I can get this to work!!
public void recordResult(String division, String teamA, String teamB, int teamAScore, int teamBScore)
{
List<Team> results = teams.get(division);
for (String i : teams.keySet())
{
results = new ArrayList<Team>();
results.add();
}
}
**You can ignore the arguments after the "String division". These will be used later.
Iterate over the entrySet() of the Map. Now you can fetch each List for that specific key and proceed further. Something like:
for (Entry<String, ArrayList<Team>> entry : teams.entrySet()) {
// extract the value from the key using `teams.get(entry.getKey())`
// proceed further with the value obtained
}
I have this school question:
The method should returns no value but should take as its argument a map whose keys are strings and whose values are integers. The strings represent person numbers and the integers the respective sales figures. The map entries do not need to be in any particular order.
For each Person in personSet your method should check whether its personNumber is one of the keys in the map. If so, the sales for that Person should be increased by the map value corresponding to that key.
This is the code i got, obviously it's incorrect, any pointers?
public void updatePersons (Map<String, Integer> pers)
{
for (Persons all : personSet)
{
if (all.getPersonNumber().equals(pers.keySet()))
{
personSet.add(pers);
}
}
}
Since a lot of code is missing I'm working on some assumptions:
If you want to update the reference number of the persons in the set based on the map you can do it like this:
for (Persons person: personSet) {
Integer reference = pers.get( person.getPersonNumber() );
if( reference != null ) {
person.setReference( reference );
}
}
You iterate over all persons and query the map for the value associated with the person number. If such a value exists you update the person and go on with the next person.
Note that if the reference number is used to sort the set you'd have to remove and reinsert the person to preserve order.