I have HashMap like:
static HashMap<String,ArrayList<Media>> mediaListWithCategory=new HashMap<String,ArrayList<Media>>();
I have value like:
January:
-Sunday
-Monday
Februsry:
-Saturday
-Sunday
-Thursday
March:
-Monday
-Tuesday
-Wednesday
How can I statically assign these values when defining the hash map?
You can populate it in a static block:
static {
map.put("January", Arrays.asList(new Media("Sunday"), new Media("Monday")));
}
(You should prefer interface to concrete classes. define your type as Map<String, List<Media>>)
Use a static block:
static {
mediaListWithCategory.put(youKey, yourValue);
}
A variant of this may be more succinct:
static HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>() {{
put("January", new ArrayList<String>() {{
add("Sunday");
add("Monday");
}});
put("Februsry" /* sic. */, new ArrayList<String>() {{
add("Saturday");
add("Sunday");
add("Thursday");
}});
put("March", new ArrayList<String>() {{
add("Monday");
add("Tuesday");
add("Wednesday");
}});
}};
See Double Brace Initialisation for discussion.
Related
I am trying to add a Key(String), Value(HashMap) to another HashMap. I somehow keep jumbling up the syntax and logic here. How do I do that? I have a kmap here initialized and then I want to add a key which is a string, and a value which is another HashMap<String, List<Integer>>)
These can be seen in the parameters below:
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void AddMapToList_ofMAP_(HashMap<String, List<Integer>> value, String key) {
if (!kmap.containsKey(key)) {
kmap.put(key, new HashMap<String, List<Integer>>());
}
HashMap<String, List<Integer>> q = kmap.get(key);
q.put(key, value);
}
It's WAY simpler than you're making it seem. You don't need a separate method, just invoke the put(key, value) method on your kmap. Assuming you have a Map<String, List<Integer>> in a variable named value, it's just:
kmap.put(key, value);
That's all. Just one line.
In your parameters you have got a HashMap called value. You are then trying to add that to the HashMap inside the HashMap but the value in that needs to be a List of integers.
Fix:
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void AddMapToList_ofMAP_(
List<Integer> value, String key) {
if (!kmap.containsKey(key)) {
kmap.put(key, new HashMap<String, List<Integer>>());
}
HashMap<String, List<Integer>> q = kmap.get(key);
q.put(key, value);
}
Also, a possible way to make this better is using an Object. I'm not sure how the code and what your putting in but an object could work.
I'm also seeing you get the HashMap by the key but you also put that key in the HashMap (The one inside), surely you could just have 1 HashMap there.
I'm not sure what exactly you are trying to achieve here. Here's what possibly you may want to do. Feel free to write more test cases and optimize the code. However this will give you a based structure to work on.
public class Stackoverflow {
static HashMap<String, HashMap<String, List<Integer>>> kmap = new HashMap<String, HashMap<String, List<Integer>>>();
public synchronized static void addIntegerToKmap(String kmapKey, String intMapKey, Integer value) {
if (!kmap.containsKey(kmapKey)) {
Map<String, List<Integer>> intMap = new HashMap<String, List<Integer>>();
HashMap<String, List<Integer>> stringListHashMap = new HashMap<String, List<Integer>>();
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(value);
stringListHashMap.put(intMapKey, integerList);
kmap.put(kmapKey, stringListHashMap);
}
else {
HashMap<String, List<Integer>> stringListHashMap = kmap.get(kmapKey);
List<Integer> integerList = stringListHashMap.get(intMapKey);
if (integerList != null && !integerList.isEmpty()) {
integerList.add(value);
}
else {
integerList = new ArrayList<Integer>();
integerList.add(value);
stringListHashMap.put(intMapKey, integerList);
}
}
}
public static void main(String args[]) {
addIntegerToKmap("A", "A1", 1);
addIntegerToKmap("A", "A1", 2);
addIntegerToKmap("A", "A2", 12);
addIntegerToKmap("A", "A2", 22);
addIntegerToKmap("B", "B1", 1);
addIntegerToKmap("A", "A1", 3);
}
}
The logic is not clear but maybe you want this
q.put(key, value.get(key));
instead of this:
q.put(key, value);
I am curious how I can more effectively instantiate a dictionary in Java. At present I have passable code, yet I am filling it with data in a very obfuscated fashion.
Is there any way for me to initialize my dictionary similar to this? This is python for the record:
westernCanadaAdjList = { 'BC': ['AB'],
'AB': ['BC', 'SK'],
'SK': ['AB', 'MB'],
'MB': ['SK']
}
I find for presentation purposes that is a whole lot more clear.
My current code in Java:
public class Main {
public static void main(String[] args) {
//Adjacency List representation through a dictionary. Allows fast O(1) lookup time.
Map<String,ArrayList<String>> adjList = new HashMap<String,ArrayList<String>>();
//Adding values for Edmonton
adjList.put("Edmonton", new ArrayList<String>());
adjList.get("Edmonton").add("Neighbour1");
adjList.get("Edmonton").add("Neighbour2");
adjList.get("Edmonton").add("Neighbour3");
//Adding values for Vancouver
adjList.put("Vancouver", new ArrayList<String>());
adjList.get("Vancouver").add("V neighbour1");
adjList.get("Vancouver").add("V neighbour2");
System.out.println(adjList.keySet() +" And Values " + adjList.values());
for (String neighbour: adjList.get("Edmonton")){
System.out.println(neighbour);
}
for (String neighbour: adjList.get("Vancouver")){
System.out.println(neighbour);
}
}
}
Thank you very much!
Note: The original answer is over 8 years old and Java has come a long way since then. As of now I'd recommend:
var map = Map.of(
"BC", List.of("AB"),
"AB", List.of("BC", "SK"),
"SK", List.of("AB", "MB"),
"MB", List.of("SK")
);
This is the best technique I know of:
Map<String, String> myMap = new HashMap<String, String>() {{
put("foo", "bar");
put("key", "value");
//etc
}};
Note the double braces -- this is commonly called double brace initialization.
What you're actually doing is creating an anonymous inner class that extends HashMap, and your new subclass contains an initializer block, in which you can call any arbitrary code that is guaranteed to be executed before the instance can be used.
Also note the 'diamond operator' cannot be used with anonymous classes, for whatever reason.
This is a nice technique for test classes, but I tend to avoid it for production code.
EDIT: Thought I should answer your actual question!
double-brace initialization is probably the best solution in "pure" Java, your Map would specifically look like:
Map<String, List<String>> westernCanadaAdjList = new HashMap<String, List<String>> () {{
put("BC", new ArrayList<String>(){{ add("AB"); }});
put("AB", new ArrayList<String>(){{ add("BC"); add("SK"); }});
put("SK", new ArrayList<String>(){{ add("AB"); add("MB"); }});
put("MB", new ArrayList<String>(){{ add("SK"); }});
}};
... Still not super awesome. Java really does need a Map literal, and it does not have one.
For production code, I'd use a Guava's MultiMap, but honestly populating it with literals isn't much better:
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("BC", "AB");
multimap.put("AB", "BC");
multimap.put("AB", "SK");
multimap.put("SK", "SK");
multimap.put("SK", "SK");
multimap.put("SK", "SK");
I recently faced a similar issue. I represented the data as a 2d array, relatively easy to type and parse, and wrote a utility method to parse it into the data structure. e.g. for your case
static String[][] CANADA_DATA = {
{"BC"," AB"},
{"AB","BC","SK"},
// rest of Canada here
}
Example code
public Map<String, List<String>> parseIt() {
Map<String, List<String>> map = new HashMap();
for (String[] provinceData : CANADA_DATA ) {
String name = provinceData [0];
ArrayList neighbors = new ArrayList(Arrays.asList(provinceData ));
neighbors.remove(0); // remove ourself
map.put(name, neighbors);
}
return map;
}
Obviously you can change the data format and parsing code to fit your specific needs.
I agree with Louis and didn't intend to add anything.
The use of streams in this case allows you to compact the code into one line but I realize this is not an answer to your question (just to closest I could think of).
Map<String, List<String>> adjList = Stream.of(
new SimpleEntry<>("Edmonton", Arrays.asList("E N1", "E N2", "E N3")),
new SimpleEntry<>("Vancouver", Arrays.asList("V N1", "V N2", "V N3")))
.collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue()));
Yes, you can: Parse it as json:
import com.fasterxml.jackson.databind.ObjectMapper;
String json = "{'BC': ['AB']," +
"'AB': ['BC', 'SK']," +
"'SK': ['AB', 'MB']," +
"'MB': ['SK']"
"}";
Map<String, Object> map = new ObjectMapper().readValue(json, HashMap.class);
I'm trying to control some permissions on my App.
Yesterday I learn how to created Double Brace Initialization, It helped a lot. But now I'm trying to use it nested, but I'm getting a
')' expected
from the IDE (Android Studio)
Here is my code:
public static final Map<String, List> ALL_PERMISSIONS = new HashMap<String, List>() {{
put("Change-maps", new ArrayList<Integer>(){{add(R.id.button_change_view);}};);
put("Stores-info-view", new ArrayList<Integer>(){{add(R.id.details_fragment);}};);
put("Competitors-layer", new ArrayList<Integer>(){{add(R.id.switch_concorrentes);}};);
}};
am I missing something in it?
is that a bad approach?
PS: I'm trying this approach because in the future I'll use some keys with more than one View (Integer), and some keys with a list of String.
You should format/indent your code (Ctrl-Shift-F by default in Eclipse).
You'd see that your anonymous ArrayList class declaration (outside set of curly brackets) cannot be followed by a semi-colon.
Here's a formatted example that will work:
public static final Map<String, List> ALL_PERMISSIONS = new HashMap<String, List>() {
{
put("Change-maps", new ArrayList<Integer>() {
{
add(R.id.button_change_view);
}
});
put("Stores-info-view", new ArrayList<Integer>() {
{
add(R.id.details_fragment);
}
});
put("Competitors-layer", new ArrayList<Integer>() {
{
add(R.id.switch_concorrentes);
}
});
}
};
Note
Also mind the raw types or suppress the warnings.
If you look at this code:
Map<String, String> map = new HashMap<String, String>();
map.put( "string1", "string2" );
You can notice that the objects you are passing in parameters are not followed by a ;.
In your case, the second object you are passing is this one:
new ArrayList<Integer>(){{add(R.id.button_change_view);}}
So, you don't need the ; before your put's closing parenthesis, like this :
public static final Map<String, List> ALL_PERMISSIONS = new HashMap<String, List>() {{
put("Change-maps", new ArrayList<Integer>(){{add(R.id.button_change_view);}});
put("Stores-info-view", new ArrayList<Integer>(){{add(R.id.details_fragment);}});
put("Competitors-layer", new ArrayList<Integer>(){{add(R.id.switch_concorrentes);}});
}};
I would not encourage the use of double brace initilization. As this answer explains, it may
surprises your colleagues and is hard to read
harms performance
may cause problems with object equality (each object created has a
unique class object).
I would suggest, if possible, to use Guava ImmutableMap and ImmutableList
for example:
public static final Map<String, List> ALL_PERMISSIONS = ImmutableMap.<String, List>of(
"Change-maps", ImmutableList.of(R.id.button_change_view),
"Stores-info-view", ImmutableList.of(R.id.details_fragment),
"Competitors-layer", ImmutableList.of(R.id.switch_concorrentes)
);
or if you need to add more elements:
public static final Map<String, List> ALL_PERMISSIONS = new ImmutableMap.Builder<String, List>()
.put("Change-maps", ImmutableList.of(R.id.button_change_view))
.put("Stores-info-view", ImmutableList.of(R.id.details_fragment))
.put("Competitors-layer", ImmutableList.of(R.id.switch_concorrentes))
//(... and so on...
.build();
I want to do something like in this example. I can't figure out why it is not working.
myMap has no value in the main class. But if I put the value in the "putSomethingInTheMap" into the map it has the right value in the main class.
Can you give me a suggestion how to handle something like this?
public static void main(String[] args) {
Map<String, Integer> meineMap = new HashMap<>();
int wert = 1;
putSomethingInTheMap(meineMap, wert);
System.out.println(meineMap.get("A"));
}
private static void putSomethingInTheMap(Map<String, Integer> myMap, int value) {
myMap = insert(value);
}
private static Map<String, Integer> insert(int wert) {
Map<String, Integer> map = new HashMap<>();
map.put("A", wert);
return map;
}
private static void putSomethingInTheMap(Map<String, Integer> myMap, int value) {
myMap.put("A", wert);
}
Basically you are doing it method pass by refrence . In main class your creating a map and passing it to putSomethingInTheMap where it is assigned by the map returned by insert.
So if you have value in main class it is due to refrence passed to method.
Because meineMap reference is same as original. You declared a new reference with new value in insert method, and java method call is pass by value, but you are pass a reference that passed as value in parameter of putSomethingInTheMap!
private static Map<String, Integer> insert(int wert) {
Map<String, Integer> map = new HashMap<>();
map.put("A", wert);
return map;
}
This part is the mistake because what you are doing here is, for every insert operation in a map you are creating a new map ( that will be empty ofcourse) and adding a value in this map and returning this map.
Now
myMap = insert(value);
call will always get a map with only 1 value every time he makes an insert operation.
Fix:
You don't need to create a new map in insert( int wert ), you just need to call put() of java map. Code for solution is already posted by #Maurice Perry
If I want an empty map or a one element map, Java Collections has a method for that. Why is there no method for more than one element? What's the best way to create a static final map with 2 elements in it? I know I can do something like:
private static final Map<String, String> MAP = new HashMap<String, String>() {
{ put("a", "b"); put("c", "d"); }
};
But then Eclipse complains about the serialVersionUID...
The reason Collections has methods for 0 and 1 entry maps is because they are special cases... the empty Map is an immutable singleton for example.
For what you want to do, though, I'd strongly recommend using Guava. Its Immutable* collections (ImmutableMap specifically) are what you want I think:
private static final ImmutableMap<String, String> MAP = ImmutableMap.of(
"a", "b",
"c", "d");
You can do the above for small maps, and for bigger maps you can write:
private static final ImmutableMap<String, String> MAP =
ImmutableMap.<String, String>builder()
.put("a", "b")
.put("b", "c")
...
.put("y", "z")
.build();
If you don't use Guava, you'll still likely want to ensure that this map can't be changed. This is a lot uglier:
private static final Map<String, String> MAP;
static {
Map<String, String> temp = new HashMap<String, String>();
temp.put("a", "b");
temp.put("b", "c");
MAP = Collections.unmodifiableMap(temp);
}
Mutable objects like maps chan be changed even if they are static and final. Final just means that the reference to the object can't change. You don't need to add the objects on initialization. The map can be added to and otherwise modified in other areas of the code, but you cannot assign a different object to the variable MAP later.
If you want it to be initialized with two items, you can add them in a static block after the declaration.
static {
MAP.put("a", "b");
MAP.put("c", "d");
}
This article has some good information on how static blocks work.
If you want an immutable map with two items, you can use a static block again like so:
private static final Map<String, String> MAP;
static {
Map<String, String> tempMap = new HashMap<String, String>();
tempMap.put("a", "b");
tempMap.put("c", "d");
MAP = Collections.unmodifiableMap(tempMap);
}
Try this (modified version of what Mark Storer wrote):
private static final Map<String, String> Map = buildMap();
private static Map<String, String> buildMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("a", "b");
map.put("c", "d");
return Collections.unmodifiableMap(map);
}
Use the return value of a static function:
private static final Map<String, String> Map = buildMap();
private static Map<String, String> buildMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("a", "b");
map.put("c", "d");
return map;
}
EDIT: Nope. My C/C++ "const" thinking is showing. A final variable may only be assigned once, but the object assigned to that variable is still quite mutable.
If they provide 0..N for any N you would be asking why isn't N+1 supported. N=0 and N=1 are easily handled special cases.