I have trouble incrementing. Why? [duplicate] - java

This question already has answers here:
Why cannot I increment returned value?
(5 answers)
Closed last month.
What's wrong with this? Specifically, what's wrong with intCount.put(i, intCount.get(i)++)?
public static Map<Integer, Integer> countNumbers(List<Integer> list) {
Map<Integer, Integer> intCount = new TreeMap<>();
for (Integer i : list) {
if (intCount.get(i) == null) {
intCount.put(i, 1);
} else {
intCount.put(i, ++intCount.get(i));
}
}
return intCount;
}
This works, on the other hand
public static Map<Integer, Integer> countNumbers(List<Integer> list) {
Map<Integer, Integer> intCount = new TreeMap<>();
for (Integer i : list) {
if (intCount.get(i) == null) {
intCount.put(i, 1);
} else {
intCount.put(i, intCount.get(i) + 1);
}
}
return intCount;
}
Does it mean I can't increment Integers, only int primitives? The problem is when I cast Integer into its respective primitive (or rather, an Integer returning method into its respective primitive) like this
intCount.put(i, ++(int)(intCount.get(i)));
it doesn't work either! Why?
Main.java:30: error: unexpected type
intCount.put(i, ++(int)(intCount.get(i)));
^
required: variable
found: value
1 error

intCount.get(i) gets a value, there is no variable to increment. Regardless, I would remove the if and else entirely and use Map.getOrDefault(Object, V) like
intCount.put(i, intCount.getOrDefault(i, 0) + 1);

Related

Exception in "main"java.lang.NullPointerException:Cannot invoke "java.lang.Integer.intValue()"the return value of "java.util.Map.get(Object)" is null [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I'm having trouble with this code. I copied this code from the book.. What is the problem??
import java.io.*;
import java.util.*;
public class WordCount {
// minimum number of occurrences needed to be printed
public static final int OCCURRENCES = 2000;
public static void main(String[] args) throws FileNotFoundException {
System.out.println("This program displays the most");
System.out.println("frequently occurring words from");
System.out.println("the book Moby Dick.");
System.out.println();
// read the book into a map
Scanner in = new Scanner(new File("moby.txt"));
Map<String, Integer> wordCountMap = getCountMap(in);
for (String word : wordCountMap.keySet()) {
int count = wordCountMap.get(word);
if (count > OCCURRENCES) {
System.out.println(word + " occurs " + count + " times.");
}
}
}
// Reads book text and returns a map from words to counts.
public static Map<String, Integer> getCountMap(Scanner in) {
Map<String, Integer> wordCountMap = new TreeMap<String, Integer>();
while (in.hasNext()) {
String word = in.next().toLowerCase();
if (wordCountMap.containsKey(word)) {
// never seen this word before
wordCountMap.put(word, 1);
} else {
// seen this word before; increment count
int count = wordCountMap.get(word);
wordCountMap.put(word, count + 1);
}
}
return wordCountMap;
}
}
Map is declared as Map<String, Integer> which means values are objects of type Integer and they can be null. On the other hand, in line int count = wordCountMap.get(word); variable count is of type int which cannot be null. And in this situation Java uses autoboxing to convert Integer to int calling Integer.intValue() under the hood, but what happens if returned value is null? Calling any method on null will throw NullPointerException like you have here.
To summarize: java doesn't know how to convert null of Integer type into int type.

Converting an Array to a List and then to a Map

i would like if someone can check out this piece of code, the code should transform an array into a list and then into a map. The key should have the value of the list element and the value should be True if it's an even number and False if it's odd. The array is "8, 6, 1, 5, 3, 9, 2". I'm pretty sure this is the right way but when printing the map i get a lot of lines, it's my first time doing with maps so i'm not sure if that's the way it should be or i messed something up huh. Code:
static public void toMap(int x[]) {
List<Integer> list = new ArrayList<>();
Map<Integer, String> map = new HashMap<>();
for (int t : x) {
list.add(t);
}
for(int z : list) {
String tf;
if(z % 2 == 0)
tf = "True";
else
tf = "False";
map.put(z,tf);
for (Map.Entry<Integer, String> mp : map.entrySet()) {
System.out.println(mp.getKey() + "/" + mp.getValue());
}
}
}
Getting this when printing:
Any help/tip would be appreciated, thanks in advance!
You are printing inside the for loop and that is causing the issue. You need to move it outside the for loop. Here is the updated code -
static public void toMap(int[] x) {
List<Integer> list = new ArrayList<>();
for (int t : x) {
list.add(t);
}
Map<Integer, String> map = new HashMap<>();
for(int z : list) {
String tf;
if(z % 2 == 0)
tf = "True";
else
tf = "False";
map.put(z,tf);
}
for (Map.Entry<Integer, String> mp : map.entrySet()) {
System.out.println(mp.getKey() + "/" + mp.getValue());
}
}
Also you can simplify it a bit as below -
public static void main(String[] args) {
Integer[] array = {8, 6, 1, 5, 3, 9, 2};
toMap(array);
}
static public void toMap(Integer[] x) {
List<Integer> list = Arrays.asList(x);
Map<Integer, String> map = new HashMap<>();
list.forEach(i -> {
if (i % 2 == 0)
map.put(i, "True");
else
map.put(i, "False");
});
System.out.println(map);
}
You are putting the loop for printing out the map inside the loop that creates it, so every time you add an entry it reprints the map. You actually do have the correct map -- the last few lines of output.
To fix it you should move that last for loop out to make it
for(int z : list) {
String tf;
if(z % 2 == 0)
tf = "True";
else
tf = "False";
map.put(z,tf);
}
for (Map.Entry<Integer, String> mp : map.entrySet()) {
System.out.println(mp.getKey() + "/" + mp.getValue());
}
This is a clear example of why you should always put the braces in your code, you get lost.
for(int z : list) {
String tf;
if(z % 2 == 0) {
tf = "True";
}
else {
tf = "False";
}
map.put(z,tf);
for (Map.Entry<Integer, String> mp : map.entrySet()) {
System.out.println(mp.getKey() + "/" + mp.getValue());
}
}
If we put the braces there, you can clearly see that you have the printing for-loop inside the other one. This is harder to see without the braces.
Move that printing loop outside the other one and you should be good.
You need to move the printing loop outside of the first loop.
Also, a few observations.
X == Y returns true or false depending on the value. And booleans will print out as true or false. So why not do the following:
for(int z : list) { // you can also replace list with your array here
map.put(z,z % 2 == 0);
}
// or if you want Strings
for (int z : list) {
map.put(z, z % 2 == 0 ? "True":"False");
}
To print them, you can do this.
map.forEach((k,v)->System.out.println(k + "/" + v));
You don't need to iterate twice over the array. Iterate only once, add it to list and even or odd to map.
static public void toMap(int x[]) {
// List which contains all elements of x.
List<Integer> list = new ArrayList<>();
// Map to store element as key and even or not as value
Map<Integer, Boolean> map = new HashMap<>();
for (int value: x) {
list.add(value);
map.put(value, value % 2 == 0);
}
// Printing the map
for (Map.Entry<Integer, Boolean> m : map.entrySet()) {
System.out.println(m.getKey() + "," + m.getValue());
}
}
As others have said, your problem is in the nesting. You are looping through all of your map entries for every integer in the input array. That said, I think the bigger issue is you have over-complicated your method. Using a few tricks, you can simplify your code down to something like this:
public static void toMap(int[] x) {
HashMap<Integer, String> map = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
for (int i : x) {
map.put(i, (i & 1) == 0 ? "True" : "False"); //puts "True" if i is even, else "False"
}
list.addAll(map.keySet()); //adds all the map's keys to the ArrayList
map.forEach((k, v) -> System.out.printf("%d/%s%n", k, v)); //prints out all the entries formatted as you specified
}
Or, if you don't actually need the ArrayList for anything specific, you can just get rid of it:
public static void toMap(int[] x) {
HashMap<Integer, String> map = new HashMap<>();
for (int i : x) {
map.put(i, (i & 1) == 0 ? "True" : "False"); //puts "True" if i is even, else "False"
}
map.forEach((k, v) -> System.out.printf("%d/%s%n", k, v)); //prints out all the entries formatted as you specified
}
Or, if you don't actually need any of the functions of the map, you can just get rid of that, too. Just print straight from the for loop, like so:
public static void toMap(int[] x) {
for (int i : x) {
System.out.printf("%d/%s%n", i, (i & 1) == 0 ? "True" : "False");
}
}
Or, if you don't mind the true/false being all lowercase, you can let Java do the string conversion for you:
public static void toMap(int[] x) {
for (int i : x) {
System.out.printf("%d/%s%n", i, (i & 1) == 0);
}
}
Finally, if you're into one-liners, and don't mind it being a bit messy, you can do it all in one line:
public static void toMap(int[] x) {
IntStream.of(x).forEach((i) -> System.out.printf("%d/%s%n", i, (i & 1) == 0));
}

How to use Map.merge for incrementing the counter as value?

I am trying to refactor a method that counts keys in HashMap in a more efficient way by implementing Map.merge(). How can I achieve it on the following code:
public Map<Character, Integer> countCharacterUsage(String input) {
Map<Character, Integer> characterToCountUsage = new WeakHashMap<>();
for (char symbol : input.toCharArray()) {
if (characterToCountUsage.containsKey(symbol)) {
int symbolsCount = characterToCountUsage.get(symbol);
characterToCountUsage.put(symbol, ++symbolsCount);
} else {
characterToCountUsage.put(symbol, 1);
}
}
return characterToCountUsage;
}
You can use compute
characterToCountUsage.compute(symbol, (k,v)-> v==null ? 1 : v+1);
Also with merge
characterToCountUsage.merge(symbol,1, (k,v)-> v+1);

Why does this code throw an invalidAssignmentOperator error on the * and + operators?

Why does this code throw an invalidAssignmentOperator error on the * and + operators?
public static Function<Integer, Double> tariff = t -> {
if (t = 500) {
t * t;
} else {
t + t;
}
};
There are several issues with your code:
Equality check needs == : t=500 should be t==500
When you have a complex code as lambda, the return statement is not implicit: so t*t does not return implicitly.
By multiplying/adding two integers you're trying to return a integer value while your expected return type is double, so compilation issues there.
Something like this would work:
public static Function<Integer, Integer> tariff = t -> {
if (t == 500) {
return t * t;
} else {
return t + t;
}
};
Implicit return would work for something like this:
public static Function<Integer, Integer> tariff = t -> (t == 500) ? t * t : t + t;
Using brackets {} requires the return keyword
Primtive type comparison is done with == and not =
As you ask for Double as output you need to cast (double), because int*int > int (same for +) OR use Function<Integer, Integer>
Function<Integer, Double> tariff = t -> {
if(t==500) {
return (double)t*t;
} else {
return (double)t+t;
}
};
To simplify you could do :
Function<Integer, Double> tariff = t -> t==500 ? t*t : t+t;
Your function is throwing an invalidAssignmentOperator because you are not actually assigning t*t or t+t to anything. You can try using t*=t and t+=t so that it will actually assign to t
Your method also is not returning anything and it should. An even better solution to my idea above would be to just return those values:
public static Function<Integer, Double> tariff = t -> {
if(t=500) {
return t*t;
} else {
return t+t;
}
};
Also, be sure to properly space out your code as shown by my code. It makes it much easier to read.

finding the largest variable

I have below five Integer variables and during the program, they are assigned some values randomly. I want to get the largest variable name but not the variable value. And I want to know if at least two of them have the same value. Please provide an example. Thank you.
int politics_counter = 0;
int economics_counter = 0;
int foreign_counter = 0;
int sport_counter = 0;
int weather_counter = 0;
And now for an answer (kind of)
public class MyThingie {
TreeMap<Integer, String> data = new TreeMap<Integer, String>();
public void doIt() {
...
insertElement("politics_counter", politics_counter);
insertElement("economics_counter", economics_counter);
insertElement("foreign_counter", foreign_counter);
insertElement("sport_counter", sport_counter);
insertElement("weather_counter", weather_counter);
System.out.println("Highest variable is "+data.lastEntry().getValue());
}
public void insertElement(String name, Integer i) {
if (data.get(i) == null) {
System.out.println("Element "+name+" has the name value as "+data.get(i));
}
else {
data.put(name,i);
}
}
}
and now for a more interesting answer:
public class BiggestFinder {
public void showBiggester(Object o) throws Exception {
TreeMap<Integer, String> data = new TreeMap<Integer, String)();
for (Field f : o.getDeclaredFields()) {
Object v = f.getValue(o);
if (v instanceof Integer) {
if (data.get(v)!=null) {
System.out.println("Value for "+f.getName()+" is the same as "+data.get(v));
}
else {
data.put((Integer)f.getValue(o), f.getName());
}
}
}
System.out.println("Largest is "+data.lastEntry().getValue());
}
}
which will interrogate an object and show the largest field, given that the object has members that are all Integers and that are all accessible to this method. There's a way to fudge that and improve it to make it more "robust".
As #Max suggested you can use a map for storing your variables and then manipulate the map for finding either biggest variable name or value.
// Initialize your map
HashMap<String, Integer> vars = new HashMap<String,Integer>();
// Inserting a variable
vars.put("politics_counter", new Integer(0));
// Looking for biggest variable
String biggestVar = "";
for (String key : vars.keySet()) {
if (key.length() > biggestVar.length)
biggestVar = key;
}

Categories

Resources