Java HashMap wont insert duplications - java

I am trying to put count of characters into hashMap but it wont insert.
for(int i = 0; i < N; i++) {
str1.put(s.charAt(i),
str1.getOrDefault(str1.get(s.charAt(i)), 0) + 1);
str2.put(t.charAt(i),
str2.getOrDefault(str2.get(t.charAt(i)) ,0) + 1);
}
Thanks.

The correct pattern is:
str1.put(s.charAt(i), 1 + str1.getOrDefault(s.charAt(i), 0));
Your current code is doing a lookup, by key, of the current value mapped to the character, which initially will be null.

Instead of explicitly fetching the value to increment the count, I would use compute.
basically, if v is null, it initializes to 1. Otherwise it takes the current value and adds 1.
String str = "Programming is fun";
Map<Character, Integer> map = new HashMap<>();
for(int i = 0; i < str.length(); i++) {
map.compute(str.charAt(i), (k,v)-> v == null ? 1 : v + 1);
}
map.entrySet().forEach(System.out::println);
Prints
=2
P=1
a=1
r=2
s=1
u=1
f=1
g=2
i=2
m=2
n=2
o=1
And you can also do a frequency count using streams.
Map<Character, Long> map = Arrays.stream(str.split("")).
collect(Collectors.groupingBy(s->s.charAt(0),
Collectors.counting()));

Related

Filling HashSet in a codeFights task

The goal of my daily task is to count how many groups of integers(from 1 to 10000, 10001 to 20000 etc. till 1000000) in a giving array (int [] a) are represented( as for example, a[0] =2, so it belongs to group 1).
My view on that is like:
static int countingGroups(int[] a)
{
Set<Integer> setOfGroupsExposed = new HashSet<>();
// Creating set for counting groups
List<Integer>list = IntStream.iterate(1,i->i+(1*10000)).limit(101).boxed()
.collect(Collectors.toList());
// list.forEach(System.out::println);
int res = setOfGroupsExposed.size();
for (int i = 0; i <a.length ; i++) {
for (int j = 0; j <list.size() ; j++) {
if(a[i]>=list.get(j)&& a[i]<list.get(j++))
setOfGroupsExposed.add(j);
// System.out.println(setOfGroupsExposed); - prints just empty brackets
}
}
return res;
}
And I can't understand what's wrong with my loops over here, and why Set is always empty.
You should change
if (a[i]>=list.get(j)&& a[i]<list.get(j++))
to
if (a[i]>=list.get(j)&& a[i]<list.get(j+1))
otherwise you increment j twice in each iteration, and besides, j++ returns the original value of j, so your condition has the same effect as if (a[i]>=list.get(j)&& a[i]<list.get(j)).

Finding 'distance' between elements in an array

I'm trying to solve an auto-cipher and to find the key length i need to find the 'distance' between all elements in the cipher-text.
I've found the distances between all elements in the array however i now want some way to find the frequency of each jump.
So for example, if i had a string "ababbababba" and wanted to work with a's, the frequency of jumps of 1 is 2 and the frequency of jumps of 2 is 2.
for(int i = 1; i<cipher2.length(); i++ ){
if(cipher2Array[i] == 'f') {
arrayList.add(i);
int jumpDistance = arrayList.get(i) - arrayList.get(i-1);
}
}
So basically from here, with my jumpDistance variable, how would I something like
if(jumpDistance == theSameinAnyOtherPlaceOfArray) {
counter++;
}
And output a type of table with jumpSize, frequency
You would need a HashMap<Integer, Integer>. You can store the jumpSize as a key and the corresponding frequency as value.
Yet again if you want multiple characters to be eveluated at one go, you would need a nested Map ie - a map for each character Map<Character, Map<Integer, Integer>> as suggested by #SAM.
Map<Integer, Integer> counter = new HashMap<Integer, Integer>();
for(int i = 1; i<cipher2.length(); i++ ){
if(cipher2Array[i] == 'f') {
arrayList.add(i);
int jumpDistance = arrayList.get(i) - arrayList.get(i-1);
Integer freq = counter.get(jumpdistance);
freq = freq == null ? 1 : freq+1;
counter.put(jumpDistance, freq);
}
}

Add the searching value from parameter in this function

This question follows my brevious one on how to Return value of smallest index of repeated number in array.
In this function given to me by #Andreas:
private static void printFirstIndexOfRepeated(int[] values) {
Integer firstIndex = null;
Map<Integer, Integer> mapValueToIndex = new HashMap<>();
for (int i = 0; i < values.length; i++) {
Integer prevIndex = mapValueToIndex.put(values[i], i); // put() returns old value, or null
if (prevIndex != null && (firstIndex == null || prevIndex < firstIndex))
firstIndex = prevIndex;
}
if (firstIndex != null)
System.out.println("First index of repeated: " + firstIndex);
else
System.out.println("No repeat found");
}
Function test:
int [] array = {10,5, 4, 3, 5, 6};
printFirstIndexOfRepeated(array);
Output
First index of repeated: 1 // it looks for 5 and return the value of smallest index of repeated 5 in array.
Due to my lack of programming knowledge with Map, I'm new and I know only Array. I need some help to transform this function and add another parameter like (int number) to decide witch number I'm looking for and not automatically
The desired one: printFirstIndexOfRepeated(int[] values, int number)
So because you basically just want the index of the first occurrence of a given number inside an array, you don't need the Map at all. Instead you can just use a simple for loop:
private static int printFirstIndexOfRepeated(int[] values,int number) {
for(int i = 0; i < values.length; i++){
if(values[i] == number){
//System.out.println("The first index of " + number + " is " + i);
return i;
}
}
//System.out.println(number + " is not a member of the array.");
return -1;
}
This function returns the first index of a given number or -1 if the number was not found. You can uncomment the print lines to also get an output if you like (or just delete them).

Java - creation of multiple object of a same kind and storing them in 2d arrayList map

I need to create 30 objects of the same kind and their name should start with a capital letter e.g "K" and after the letter i need the index of the object
e.g K1 ; K2 ... K30
Is there any way to enter a loop which has a counter and which will work properly
something like this
for (int i = 0; i<20;i++){
K k = new K();
k.setName("k" + i)
}
I also have a map which is 2d ArrayList 20x20
and all this object need to have a random position x and y into this array list
i could generate random numbers easily but how to use them to put the objects in the array list
Thank you for your time !
Provided you have a class K, with setName() method, you can do the following:
List<K> list = new ArrayList<K>();
for(int i=1 ; i<=30 ; i++){
K k = new K();
k.setName("K" + i);
list.add(k);
}
Your code is fine, just set the limit to 30, if you want a list for your objects, you have to create a list and add objects, for example
List<K> kObjects = new ArrayList<K>();
for (int i = 1; i <= 30; i++){
K k = new K();
k.setName("K" + i);
kObjects.add(k);
}
Hope it helps to you

Find unique items from two arrays

I was wondering what could be a better solution that could produce less complexity than O(n^2) when printing unique items from two arrays. Any ideas?
int[] a = {1,2,4,5,8};
int[] b = {3,2,5,7,8};
ArrayList unMatch = new ArrayList() ;
for(int i=0; i<a.length; i++){
boolean contains = false;
innerloop:
for(int k =0; k<b.length; k++){
if(a[i]==b[k]){
contains = true;
break innerloop;
}
}
if(!contains){
unMatch.add(a[i]);
}
}
for(int i=0; i<b.length; i++){
boolean contains = false;
innerloop:
for(int k =0; k<a.length; k++){
if(b[i]==a[k]){
contains = true;
break innerloop;
}
}
if(!contains){
unMatch.add(b[i]);
}
}
Output: [1,4,3,7]
I think this sort of solution will be better, if you can use other data structures:
First we will fill up a HashMap<Integer, Integer> with the items and their frequencies:
public static Set<Entry<Integer, Integer>> fillMap(int[] a, int[] b) {
HashMap<Integer, Integer> entries = new HashMap<>();
for (Integer i : a)
entries.put(i, entries.get(i) == null ? 1 : entries.get(i) + 1);
for (Integer i : b)
entries.put(i, entries.get(i) == null ? 1 : entries.get(i) + 1);
return entries.entrySet();
}
And then print the unique items (the ones with value = 1):
for (Entry<Integer, Integer> entry: fillMap(a, b))
if (entry.getValue() == 1)
System.out.println("This value is unique: " + entry.getKey() );
If I'm not mistaken this should run in O(n+m) (or just O(n) if the arrays are the same length always).
convert array to array list
List<Integer> c = Array.asList(a);
List<Integer> d = Array.asList<b>;
c.removeAll(d);
c.addAll(d);
c.froEach(System.out::println);
I did this in java using lambdas it is only O(n)
Hope this code answers your question
Use of Set can reduce your complexity. Sets don't allow duplicates. Sets can be:
HashSet - HashSet is implemented using a hash table. Elements are not ordered. The add, remove, and contains methods have constant time complexity O(1).
LinkedHashSet - uses Trees (RB-Trees). Elements are not ordered. Complexity for the same methods is O(log n)
TreeSet - uses a hash table with a linked list running through it. Elements are ordered. The time complexity of the same methods is O(1).
E.g.
HashSet<Integer> set = new HashSet<>();
for(int n : a) {
set.add(n);
}
for (int n : b) {
set.add(n);
}
So, it provides a linear order here - O(n+m).

Categories

Resources