How to count frequency of characters in a string? - java

I need to write some kind of loop that can count the frequency of each letter in a string.
For example: "aasjjikkk" would count 2 'a', 1 's', 2 'j', 1 'i', 3 'k'. Ultimately id like these to end up in a map with the character as the key and the count as the value. Any good idea how to do this?

You can use a java Map and map a char to an int. You can then iterate over the characters in the string and check if they have been added to the map, if they have, you can then increment its value.
For example:
Map<Character, Integer> map = new HashMap<Character, Integer>();
String s = "aasjjikkk";
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
Integer val = map.get(c);
if (val != null) {
map.put(c, val + 1);
}
else {
map.put(c, 1);
}
}
At the end you will have a count of all the characters you encountered and you can extract their frequencies from that.
Alternatively, you can use Bozho's solution of using a Multiset and counting the total occurences.

Using the stream API as of JDK-8:
Map<Character, Long> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
or if you want the keys as Integers:
Map<Character, Integer> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(c -> 1)));
Another variant:
Map<Character, Integer> frequency =
str.chars()
.mapToObj(c -> (char)c)
.collect(Collectors.toMap(Function.identity(), c -> 1, Math::addExact));

A concise way to do this is:
Map<Character,Integer> frequencies = new HashMap<>();
for (char ch : input.toCharArray())
frequencies.put(ch, frequencies.getOrDefault(ch, 0) + 1);
We use a for-each to loop through every character. The frequencies.getOrDefault() gets value if key is present or returns(as default) its second argument.

You can use a Multiset (from guava). It will give you the count for each object. For example:
Multiset<Character> chars = HashMultiset.create();
for (int i = 0; i < string.length(); i++) {
chars.add(string.charAt(i));
}
Then for each character you can call chars.count('a') and it returns the number of occurrences

Here is another solution, dodgy as it may be.
public char getNumChar(String s) {
char[] c = s.toCharArray();
String alphabet = "abcdefghijklmnopqrstuvwxyz";
int[] countArray = new int[26];
for (char x : c) {
for (int i = 0; i < alphabet.length(); i++) {
if (alphabet.charAt(i) == x) {
countArray[i]++;
}
}
}
java.util.HashMap<Integer, Character> countList = new java.util.HashMap<Integer, Character>();
for (int i = 0; i < 26; i++) {
countList.put(countArray[i], alphabet.charAt(i));
}
java.util.Arrays.sort(countArray);
int max = countArray[25];
return countList.get(max);
}

Since there was no Java 8 solution, thought of posting one. Also, this solution is much neater, readable and concise than some of the other solutions mentioned here.
String string = "aasjjikkk";
Map<Character, Long> characterFrequency = string.chars() // creates an IntStream
.mapToObj(c -> (char) c) // converts the IntStream to Stream<Character>
.collect(Collectors.groupingBy(c -> c, Collectors.counting())); // creates a
// Map<Character, Long>
// where the Long is
// the frequency

Well, two ways come to mind and it depends on your preference:
Sort the array by characters. Then, counting each character becomes trivial. But you will have to make a copy of the array first.
Create another integer array of size 26 (say freq) and str is the array of characters.
for(int i = 0; i < str.length; i ++)
freq[str[i] - 'a'] ++; //Assuming all characters are in lower case
So the number of 'a' 's will be stored at freq[0] and the number of 'z' 's will be at freq[25]

Here is a solution:
Define your own Pair:
public class Pair
{
private char letter;
private int count;
public Pair(char letter, int count)
{
this.letter = letter;
this.count= count;
}
public char getLetter(){return key;}
public int getCount(){return count;}
}
Then you could do:
public static Pair countCharFreq(String s)
{
String temp = s;
java.util.List<Pair> list = new java.util.ArrayList<Pair>();
while(temp.length() != 0)
{
list.add(new Pair(temp.charAt(0), countOccurrences(temp, temp.charAt(0))));
temp.replaceAll("[" + temp.charAt(0) +"]","");
}
}
public static int countOccurrences(String s, char c)
{
int count = 0;
for(int i = 0; i < s.length(); i++)
{
if(s.charAt(i) == c) count++;
}
return count;
}

String s = "aaaabbbbcccddddd";
Map<Character, Integer> map = new HashMap<>();
Using one line in Java8
s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));

You can use a CharAdapter and a CharBag from Eclipse Collections and avoid boxing to Character and Integer.
CharBag bag = Strings.asChars("aasjjikkk").toBag();
Assert.assertEquals(2, bag.occurrencesOf('a'));
Assert.assertEquals(1, bag.occurrencesOf('s'));
Assert.assertEquals(2, bag.occurrencesOf('j'));
Assert.assertEquals(1, bag.occurrencesOf('i'));
Assert.assertEquals(3, bag.occurrencesOf('k'));
Note: I am a committer for Eclipse Collections.

There is one more option and it looks quite nice.
Since java 8 there is new method merge java doc
public static void main(String[] args) {
String s = "aaabbbcca";
Map<Character, Integer> freqMap = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
Character c = s.charAt(i);
freqMap.merge(c, 1, (a, b) -> a + b);
}
freqMap.forEach((k, v) -> System.out.println(k + " and " + v));
}
Or even cleaner with ForEach
for (Character c : s.toCharArray()) {
freqMapSecond.merge(c, 1, Integer::sum);
}

package com.rishi.zava;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class ZipString {
public static void main(String arg[]) {
String input = "aaaajjjgggtttssvvkkllaaiiikk";
int len = input.length();
Map<Character, Integer> zip = new HashMap<Character, Integer>();
for (int j = 0; len > j; j++) {
int count = 0;
for (int i = 0; len > i; i++) {
if (input.charAt(j) == input.charAt(i)) {
count++;
}
}
zip.put(input.charAt(j), count);
}
StringBuffer myValue = new StringBuffer();
String myMapKeyValue = "";
for (Entry<Character, Integer> entry : zip.entrySet()) {
myMapKeyValue = Character.toString(entry.getKey()).concat(
Integer.toString(entry.getValue()));
myValue.append(myMapKeyValue);
}
System.out.println(myValue);
}
}
Input = aaaajjjgggtttssvvkkllaaiiikk
Output = a6s2t3v2g3i3j3k4l2

If this does not need to be super-fast just create an array of integers, one integer for each letter (only alphabetic so 2*26 integers? or any binary data possible?). go through the string one char at a time, get the index of the responsible integer (e.g. if you only have alphabetic chars you can have 'A' be at index 0 and get that index by subtracting any 'A' to 'Z' by 'A' just as an example of how you can get reasonably fast indices) and increment the value in that index.
There are various micro-optimizations to make this faster (if necessary).

You can use a Hashtable with each character as the key and the total count becomes the value.
Hashtable<Character,Integer> table = new Hashtable<Character,Integer>();
String str = "aasjjikkk";
for( c in str ) {
if( table.get(c) == null )
table.put(c,1);
else
table.put(c,table.get(c) + 1);
}
for( elem in table ) {
println "elem:" + elem;
}

This is similar to xunil154's answer, except that a string is made a char array and a linked hashmap is used to maintain the insertion order of the characters.
String text = "aasjjikkk";
char[] charArray = text.toCharArray();
Map<Character, Integer> freqList = new LinkedHashMap<Character, Integer>();
for(char key : charArray) {
if(freqList.containsKey(key)) {
freqList.put(key, freqList.get(key) + 1);
} else
freqList.put(key, 1);
}

import java.util.*;
class Charfrequency
{
public static void main(String a[]){
Scanner sc=new Scanner(System.in);
System.out.println("Enter Your String :");
String s1=sc.nextLine();
int count,j=1;
char var='a';
char ch[]=s1.toCharArray();
while(j<=26)
{
count=0;
for(int i=0; i<s1.length(); i++)
{
if(ch[i]==var || ch[i]==var-32)
{
count++;
}
}
if(count>0){
System.out.println("Frequency of "+var+" is "+count);
}
var++;
j++;
}
}
}

The shorted possible code using a HashMap. (With no forceful line saves)
private static Map<Character, Integer> findCharacterFrequency(String str) {
Map<Character, Integer> map = new HashMap<>();
for (char ch : str.toCharArray()) {
/* Using getOrDefault(), since Java1.8 */
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
return map;
}

Please try the given code below, hope it will helpful to you,
import java.util.Scanner;
class String55 {
public static int frequency(String s1,String s2)
{
int count=0;
char ch[]=s1.toCharArray();
char ch1[]=s2.toCharArray();
for (int i=0;i<ch.length-1; i++)
{
int k=i;
int j1=i+1;
int j=0;
int j11=j;
int j2=j+1;
{
while(k<ch.length && j11<ch1.length && ch[k]==ch1[j11])
{
k++;
j11++;
}
int l=k+j1;
int m=j11+j2;
if( l== m)
{
count=1;
count++;
}
}
}
return count;
}
public static void main (String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("enter the pattern");
String s1=sc.next();
System.out.println("enter the String");
String s2=sc.next();
int res=frequency(s1, s2);
System.out.println("FREQUENCY==" +res);
}
}
SAMPLE OUTPUT:
enter the pattern
man
enter the String
dhimanman
FREQUENCY==2
Thank-you.Happy coding.

package com.dipu.string;
import java.util.HashMap;
import java.util.Map;
public class RepetativeCharInString {
public static void main(String[] args) {
String data = "aaabbbcccdddffffrss";
char[] charArray = data.toCharArray();
Map<Character, Integer> map = new HashMap<>();
for (char c : charArray) {
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
System.out.println(map);
}
}

*import java.util.ArrayList;
import java.util.Collections;
public class Freq {
public static void main(String[] args) {
// TODO Auto-generated method stub
String temp="zsaaqaaaaaaaabbbbbcc";
List<String> temp1= new ArrayList<String> ();
ArrayList<Integer>freq=new ArrayList<Integer>();
for(int i=0;i<temp.length()-1;i++)
{
temp1.add(Character.toString(temp.charAt(i)));
}
Set<String> uniqset=new HashSet<String>(temp1);
for(String s:uniqset)
{
freq.add(Collections.frequency(temp1, s));
System.out.println(s+" -->>"+Collections.frequency(temp1, s));
}
}
}
------Output-------
a -->>10
b -->>5
c -->>1
q -->>1
s -->>1
z -->>1
Use collections frequency method to count frequency of char*

Uffh. Don't you think this is the simplest solution?
char inputChar = '|';
int freq = "|fd|fdfd|f dfd|fd".replaceAll("[^" + inputChar +"]", "").length();
System.out.println("freq " + freq);

We can use frequency method of Collections class for this.
Split the string into string array. Use HashSet to remove duplicates and check frequency of each object in HashSet using frequency method of Collections
void usingCollections(){
String input = "cuttack";
String [] stringArray = input.split("");
Set<String> s = new HashSet(Arrays.asList(stringArray));
for(String abc : s){
System.out.println (abc + ":"+Collections.frequency(Arrays.asList(stringArray),abc));
}
}

This is more Effective way to count frequency of characters in a string
public class demo {
public static void main(String[] args) {
String s = "babdcwertyuiuygf";
Map<Character, Integer> map = new TreeMap<>();
s.chars().forEach(e->map.put((char)e, map.getOrDefault((char)e, 0) + 1));
StringBuffer myValue = new StringBuffer();
String myMapKeyValue = "";
for (Map.Entry<Character, Integer> entry : map.entrySet()) {
myMapKeyValue = Character.toString(entry.getKey()).concat(
Integer.toString(entry.getValue()));
myValue.append(myMapKeyValue);
}
System.out.println(myValue);
}
}

Another way using map merge method
Map<Character, Integer> map = new HashMap<>();
String s = "aasjjikkk";
for (int i = 0; i < s.length(); i++) {
map.merge(s.charAt(i), 1, (l, r) -> l + r);

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
public class FrequenceyOfCharacters {
public static void main(String[] args) {
System.out.println("Please enter the string to count each character frequencey: ");
Scanner sc=new Scanner(System.in);
String s =sc.nextLine();
String input = s.replaceAll("\\s",""); // To remove space.
frequenceyCount(input);
}
private static void frequenceyCount(String input) {
Map<Character,Integer> hashCount=new HashMap<>();
Character c;
for(int i=0; i<input.length();i++)
{
c =input.charAt(i);
if(hashCount.get(c)!=null){
hashCount.put(c, hashCount.get(c)+1);
}else{
hashCount.put(c, 1);
}
}
Iterator it = hashCount.entrySet().iterator();
System.out.println("char : frequency");
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " : " + pairs.getValue());
it.remove();
}
}
}

import java.io.FileInputStream;
import java.util.HashSet;
import java.util.Iterator;
public class CountFrequencyOfCharater {
public static void main(String args[]) throws Exception
{
HashSet hs=new HashSet();
String str="hey how are you?";
char arr[]=new char[str.length()];
for(int i=0;i<str.length();i++)
{
arr[i]=str.charAt(i);
}
for(int j=0;j<str.length();j++)
{
int c=0;
for(int k=0;k<str.length();k++)
{
if(arr[j]==arr[k])
c++;
}
hs.add(arr[j]+"="+c+",");
}
Iterator it=hs.iterator();
while(it.hasNext())
{
System.out.print(it.next());
}
}
}

#From C language
#include<stdio.h>`
#include <string.h>`
int main()
{
char s[1000];
int i,j,k,count=0,n;
printf("Enter the string : ");
gets(s);
for(j=0;s[j];j++);
n=j;
printf(" frequency count character in string:\n");
for(i=0;i<n;i++)
{
count=1;
if(s[i])
{
for(j=i+1;j<n;j++)
{
if(s[i]==s[j])
{
count++;
s[j]='\0';
}
}
printf(" '%c' = %d \n",s[i],count);
}
}
return 0;
}

Related

How to find duplicate character in string without using in built methods of String Class in java methods like length(),toCharArray(),charAt()?

How to find the duplicate character in the string without using inbuilt methods of String Class in java methods like length(), toCharArray(), charAt()?
Ask in an interview please give me solutions on this
input : abcdeddrb
output: db
You can do this with reflection:
public String findDuplicateChars(String input)
throws NoSuchFieldException, IllegalAccessException {
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] chars = (char[]) valueField.get(input);
List<Character> duplicatedChars = new ArrayList<>();
for (int i = 0; i < chars.length; i++) {
char aChar = chars[i];
for (int j = i + 1; j < chars.length; j++) {
char anotherChar = chars[j];
if (aChar == anotherChar) {
if (!duplicatedChars.contains(aChar)) {
duplicatedChars.add(aChar);
}
}
}
}
char[] charArray = new char[duplicatedChars.size()];
for (int i = 0; i < duplicatedChars.size(); i++) {
charArray[i] = duplicatedChars.get(i);
}
return new String(charArray);
}
Since b is the first duplicated char the output will be bd though, not db.
Maybe the point of the interview's question was to check if you know reflection or to check if you would try to quit the interview with an answer like "Why should anyone do that?".
Maybe change String to CharSequence and use its methods as charAt
CharSequence cs = s;
My guess here is that your interviewer wanted you to use a map to keep track of which characters have been seen and which have not.
String input = "abcdeddrb";
Map<Character, Integer> map = new HashMap<>();
for (int i=0; i < input.length(); ++i) {
Integer count = map.get(input.charAt(i));
map.put(input.charAt(i), count == null ? 1 : count + 1);
}
map.entrySet().stream()
.filter(entry -> entry.getValue() > 1)
.forEach(System.out::println);
b=2
d=3
public static void main(String[] args) {
String testStr = "abcdeddrb";
Map<Character, Integer> map = new HashMap<>();
Map<Character, Integer> duplicateStrMap = null;
int count = 0;
int i = 0;
CharacterIterator it = new StringCharacterIterator(testStr);
// Loop Characters in a String.
for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if(map.containsKey(c)){
if(duplicateStrMap == null){
duplicateStrMap = new HashMap<>();
}
duplicateStrMap.put(c, count);
count++;
}
else{
map.put(c, ++i);
}
}
// Print Results
if(duplicateStrMap != null){
System.out.println("Total Duplcates Found :"+duplicateStrMap.size());
Iterator<Character> itr = duplicateStrMap.keySet().iterator();
System.out.println("Duplicate Characters :");
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
Output:
Total Duplcates Found :2 Duplicate Characters : b d

Common characters in n strings

I m trying to make a function that prints the number of characters common in given n strings. (note that characters may be used multiple times)
I am struggling to perform this operation on n strings However I did it for 2 strings without any characters repeated more than once.
I have posted my code.
public class CommonChars {
public static void main(String[] args) {
String str1 = "abcd";
String str2 = "bcde";
StringBuffer sb = new StringBuffer();
// get unique chars from both the strings
str1 = uniqueChar(str1);
str2 = uniqueChar(str2);
int count = 0;
int str1Len = str1.length();
int str2Len = str2.length();
for (int i = 0; i < str1Len; i++) {
for (int j = 0; j < str2Len; j++) {
// found match stop the loop
if (str1.charAt(i) == str2.charAt(j)) {
count++;
sb.append(str1.charAt(i));
break;
}
}
}
System.out.println("Common Chars Count : " + count + "\nCommon Chars :" +
sb.toString());
}
public static String uniqueChar(String inputString) {
String outputstr="",temp="";
for(int i=0;i<inputstr.length();i++) {
if(temp.indexOf(inputstr.charAt(i))<0) {
temp+=inputstr.charAt(i);
}
}
System.out.println("completed");
return temp;
}
}
3
abcaa
bcbd
bgc
3
their may be chances that a same character can be present multiple times in
a string and you are not supposed to eliminate those characters instead
check the no. of times they are repeated in other strings. for eg
3
abacd
aaxyz
aatre
output should be 2
it will be better if i get solution in java
You have to convert all Strings to Set of Characters and retain all from the first one. Below solution has many places which could be optimised but you should understand general idea.
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> input = Arrays.asList("jonas", "ton", "bonny");
System.out.println(findCommonCharsFor(input));
}
public static Collection<Character> findCommonCharsFor(List<String> strings) {
if (strings == null || strings.isEmpty()) {
return Collections.emptyList();
}
Set<Character> commonChars = convertStringToSetOfChars(strings.get(0));
strings.stream().skip(1).forEach(s -> commonChars.retainAll(convertStringToSetOfChars(s)));
return commonChars;
}
private static Set<Character> convertStringToSetOfChars(String string) {
if (string == null || string.isEmpty()) {
return Collections.emptySet();
}
Set<Character> set = new HashSet<>(string.length() + 10);
for (char c : string.toCharArray()) {
set.add(c);
}
return set;
}
}
Above code prints:
[n, o]
A better strategy for your problem is to use this method:
public int[] countChars(String s){
int[] count = new int[26];
for(char c: s.toCharArray()){
count[c-'a']++;
}
return count;
}
Now if you have n Strings (String[] strings) just find the min of common chars for each letter:
int[][] result = new int[n][26]
for(int i = 0; i<strings.length;i++){
result[i] = countChars(s);
}
// now if you sum the min common chars for each counter you are ready
int commonChars = 0;
for(int i = 0; i< 26;i++){
int min = result[0][i];
for(int i = 1; i< n;i++){
if(min>result[j][i]){
min = result[j][i];
}
}
commonChars+=min;
}
Get list of characters for each string:
List<Character> chars1 = s1.chars() // list of chars for first string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
List<Character> chars2 = s2.chars() // list of chars for second string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
Then use retainAll method:
chars1.retainAll(chars2); // retain in chars1 only the chars that are contained in the chars2 also
System.out.println(chars1.size());
If you want to get number of unique chars just use Collectors.toSet() instead of toList()
Well if one goes for hashing:
public static int uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
int count = 0;
//reduce first string to unique letters
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
//reduce to unique letters in both strings
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
count++;
hash[c - 'a'] = false;
}
}
return count;
}
This is using bucketsort which gives a n+m complexity but needs the 26 buckets(the "hash" array).
Imo one can't do better in regards of complexity as you need to look at every letter at least once which sums up to n+m.
Insitu the best you can get is imho somewhere in the range of O(n log(n) ) .
Your aproach is somewhere in the league of O(n²)
Addon: if you need the characters as a String(in essence the same as above with count is the length of the String returned):
public static String uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
StringBuilder sb = new StringBuilder();
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
sb.append(c);
hash[c - 'a'] = false;
}
}
return sb.toString();
}
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
Set<Character> unique = words[0].chars().mapToObj(ch -> (char)ch).collect(Collectors.toCollection(TreeSet::new));
for (String word : words)
unique.retainAll(word.chars().mapToObj(ch -> (char)ch).collect(Collectors.toSet()));
return unique.stream().map(String::valueOf).collect(Collectors.joining());
}
Another variant without creating temporary Set and using Character.
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
int[] arr = new int[26];
boolean[] tmp = new boolean[26];
for (String word : words) {
Arrays.fill(tmp, false);
for (int i = 0; i < word.length(); i++) {
int pos = Character.toLowerCase(word.charAt(i)) - 'a';
if (tmp[pos])
continue;
tmp[pos] = true;
arr[pos]++;
}
}
StringBuilder buf = new StringBuilder(26);
for (int i = 0; i < arr.length; i++)
if (arr[i] == words.length)
buf.append((char)('a' + i));
return buf.toString();
}
Demo
System.out.println(getCommonCharacters("abcd", "bcde")); // bcd

Frequency of elements in an ArrayList

I am trying to write a code that finds the frequency of characters in a String entered in the method (phraseList() is an already working method that takes a word and puts each character in an arrayList)
and returns in a new List that has the letters and their frequency, my code below;
public List <String> ltrfrq(String phrase){
List <String> list0 = new ArrayList<String>();
int count = 1;
List <String> list = phraseList(phrase.toUpperCase());
for(int i = 0; i < list.size(); i++){
for(int j = i + 1; j < list.size(); j++){
if(list.get(i).equals(list.get(j))){
count++;
}
}
if(list.get(i).equals(" ")){
list0.add("Space" + "-" + count);
}
else{
list0.add(list.get(i) + "-" + count);
}
count = 1;
}
return list0;
}
}
My problem however is that it returns all the letters and although I have tried many methods to remove them like using the remove() method, it still does not work, I had something like
list.remove(list.get(i));
i--;
Can anyone help me?
HashMaps are key-value pairs. But the keys are unique. So you cannot have duplicate keys. Kind of like a dictionary, you can update the value (definition) of a word, but you won't have that word listed twice.
Watch: https://www.youtube.com/watch?v=j442WG8YzM4
Read: https://beginnersbook.com/2013/12/hashmap-in-java-with-example/
Output:
{a=4, b=3, c=2, d=1}
I'll leave it as an exercise for you to traverse the map.
import java.util.HashMap;
public class F {
public static void main(String[] args) {
String string = "aaaabbbccd";
HashMap<Character, Integer> map = frequency(string);
System.out.println(map);
}
public static HashMap<Character, Integer> frequency(String string) {
int length = string.length();
char c;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = 0; i < length; i++) {
c = string.charAt(i);
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
return map;
}
}
If I could only use List data structures (and my own custom one), this is how I would do it. I would redefine all of the add, remove functions to compensate for duplicate entries.
Output:
[{a=4}, {b=3}, {c=2}, {d=1}]
Code:
import java.util.List;
import java.util.ArrayList;
public class F {
static class Entry {
char character;
int count;
public Entry(char c, int i) {
character = c;
count = i;
}
public String toString() {
return "{" + character + "=" + count + "}";
}
}
public static void main(String[] args) {
String string = "aaaabbbccd";
List<Entry> list = frequency(string);
System.out.println(list);
}
public static List<Entry> frequency(String string) {
int length = string.length();
char c;
Entry entry;
List<Entry> list = new ArrayList<Entry>();
for (int i = 0; i < length; i++) {
c = string.charAt(i);
// add to list
add(c, list);
}
return list;
}
public static void add(char c, List<Entry> list) {
// If the list does not contain the character
if (!contains(c, list)) {
list.add(new Entry(c, 1));
} else {
// Find the entry
int index = find(c, list);
// If we found the entry's indes
if (index >= 0) {
// Get the entry
Entry temp = list.get(index);
temp.count++; // Increment its count
list.remove(index); // Delete old 1
list.add(index, temp); // Insert new 1
}
}
}
// Finds the index of an entry thats associated with a character
public static int find(char c, List<Entry> list) {
int index = -1;
int length = list.size();
Entry temp;
for (int i = 0; i < length; i++) {
temp = list.get(i);
if (temp.character == c) {
index = i;
break;
}
}
return index;
}
// Remove an Entry from list that is associate with a given character
public static List<Entry> remove(char c, List<Entry> list) {
for (Entry entry : list) {
if (entry.character == c) {
list.remove(entry);
}
}
return list;
}
// Get the entry that correlates to a give character in the list
public static Entry get(char c, List<Entry> list) {
Entry entryToReturn = null;
for (Entry entry : list) {
if (entry.character == c) {
entryToReturn = entry;
break;
}
}
return entryToReturn;
}
// Checks if the list contains the character
public static boolean contains(char c, List<Entry> list) {
boolean contains = false;
for (Entry entry : list) {
if (entry.character == c) {
contains = true;
break;
}
}
return contains;
}
}
Here is a way to do it using the new method merge() available on Java8 Map.
import java.util.HashMap;
import java.util.Map;
public class CountLetterFrequency {
public static void main(String[] args) {
System.out.println(ltrfrq("abacacdea"));
}
public static Map<Character, Integer> ltrfrq(String phrase){
Map<Character, Integer> frqMap = new HashMap<>();
for(int i=0; i<phrase.length(); i++){
frqMap.merge(phrase.charAt(i), 1, Integer::sum);
}
return frqMap;
}
}
Output:
{a=4, b=1, c=2, d=1, e=1}
With the method merge(), when the item is not in the map, it just adds it, which in this case will add key=charAt(i),value=1. On the other hand, if the key is already on the map, merge calls a function passing both current and new values, and updates the map with the result of this function.
Integer::sum is a method reference, since the merge method expects a function with two parameters, we could rewrite it as (currV,newV) -> currV+newV.
Now, if you wish, you can use the new Stream API instead. First, convert the String to an IntStream, then map each int to a Character, then collect the result on a HashMap and return it. The method ltrfrq would be as follows:
public static Map<Character, Integer> ltrfrq(String phrase){
return phrase.chars()
.mapToObj(i->(char)i)
.collect(HashMap::new,
(m,k) -> m.merge(k, 1, Integer::sum),
Map::putAll);
}
HashMap is the easier way to solving this problem. If you have to use List, you can check if the character exist in list0 first. If the character is not exist in list0 then count for its frequency.
Updated Code :
public static void main(String args[]){
ArrayList <String> list0 = new ArrayList<String>();
int count = 1;
//List <String> list = phraseList(phrase.toUpperCase());\
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("a");
list.add("c");
list.add("b");
list.add("a");
for(int i = 0; i < list.size(); i++){
boolean isDuplicate = false;
for (String s: list0){
if (s.contains(list.get(i).trim()))
isDuplicate =true;
}
if (!isDuplicate){
for(int j = i + 1; j < list.size(); j++){
if(list.get(i).equals(list.get(j))){
count++;
}
}
if(list.get(i).equals("/s")){
list0.add("Space" + "-" + count);
}
else{
list0.add(list.get(i) + "-" + count);
}
count = 1;
}
}
for (String a: list0)
System.out.println(a);
}

Same word occurrence in a string. Java [duplicate]

I am writing a very basic java program that calculates frequency of each word in a sentence so far i managed to do this much
import java.io.*;
class Linked {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Enter the sentence");
String st = br.readLine();
st = st + " ";
int a = lengthx(st);
String arr[] = new String[a];
int p = 0;
int c = 0;
for (int j = 0; j < st.length(); j++) {
if (st.charAt(j) == ' ') {
arr[p++] = st.substring(c,j);
c = j + 1;
}
}
}
static int lengthx(String a) {
int p = 0;
for (int j = 0; j < a.length(); j++) {
if (a.charAt(j) == ' ') {
p++;
}
}
return p;
}
}
I have extracted each string and stored it in a array , now problem is actually how to count the no of instances where each 'word' is repeated and how to display so that repeated words not get displayed multiple times , can you help me in this one ?
Use a map with word as a key and count as value, somthing like this
Map<String, Integer> map = new HashMap<>();
for (String w : words) {
Integer n = map.get(w);
n = (n == null) ? 1 : ++n;
map.put(w, n);
}
if you are not allowed to use java.util then you can sort arr using some sorting algoritm and do this
String[] words = new String[arr.length];
int[] counts = new int[arr.length];
words[0] = words[0];
counts[0] = 1;
for (int i = 1, j = 0; i < arr.length; i++) {
if (words[j].equals(arr[i])) {
counts[j]++;
} else {
j++;
words[j] = arr[i];
counts[j] = 1;
}
}
An interesting solution with ConcurrentHashMap since Java 8
ConcurrentMap<String, Integer> m = new ConcurrentHashMap<>();
m.compute("x", (k, v) -> v == null ? 1 : v + 1);
In Java 8, you can write this in two simple lines! In addition you can take advantage of parallel computing.
Here's the most beautiful way to do this:
Stream<String> stream = Stream.of(text.toLowerCase().split("\\W+")).parallel();
Map<String, Long> wordFreq = stream
.collect(Collectors.groupingBy(String::toString,Collectors.counting()));
import java.util.*;
public class WordCounter {
public static void main(String[] args) {
String s = "this is a this is this a this yes this is a this what it may be i do not care about this";
String a[] = s.split(" ");
Map<String, Integer> words = new HashMap<>();
for (String str : a) {
if (words.containsKey(str)) {
words.put(str, 1 + words.get(str));
} else {
words.put(str, 1);
}
}
System.out.println(words);
}
}
Output:
{a=3, be=1, may=1, yes=1, this=7, about=1, i=1, is=3, it=1, do=1, not=1, what=1, care=1}
Try this
public class Main
{
public static void main(String[] args)
{
String text = "the quick brown fox jumps fox fox over the lazy dog brown";
String[] keys = text.split(" ");
String[] uniqueKeys;
int count = 0;
System.out.println(text);
uniqueKeys = getUniqueKeys(keys);
for(String key: uniqueKeys)
{
if(null == key)
{
break;
}
for(String s : keys)
{
if(key.equals(s))
{
count++;
}
}
System.out.println("Count of ["+key+"] is : "+count);
count=0;
}
}
private static String[] getUniqueKeys(String[] keys)
{
String[] uniqueKeys = new String[keys.length];
uniqueKeys[0] = keys[0];
int uniqueKeyIndex = 1;
boolean keyAlreadyExists = false;
for(int i=1; i<keys.length ; i++)
{
for(int j=0; j<=uniqueKeyIndex; j++)
{
if(keys[i].equals(uniqueKeys[j]))
{
keyAlreadyExists = true;
}
}
if(!keyAlreadyExists)
{
uniqueKeys[uniqueKeyIndex] = keys[i];
uniqueKeyIndex++;
}
keyAlreadyExists = false;
}
return uniqueKeys;
}
}
Output:
the quick brown fox jumps fox fox over the lazy dog brown
Count of [the] is : 2
Count of [quick] is : 1
Count of [brown] is : 2
Count of [fox] is : 3
Count of [jumps] is : 1
Count of [over] is : 1
Count of [lazy] is : 1
Count of [dog] is : 1
From Java 10 you can use the following:
import java.util.Arrays;
import java.util.stream.Collectors;
public class StringFrequencyMap {
public static void main(String... args){
String[] wordArray = {"One", "One", "Two","Three", "Two", "two"};
var freq = Arrays.stream(wordArray)
.collect(Collectors.groupingBy(x -> x, Collectors.counting()));
System.out.println(freq);
}
}
Output:
{One=2, two=1, Two=2, Three=1}
You could try this
public static void frequency(String s) {
String trimmed = s.trim().replaceAll(" +", " ");
String[] a = trimmed.split(" ");
ArrayList<Integer> p = new ArrayList<>();
for (int i = 0; i < a.length; i++) {
if (p.contains(i)) {
continue;
}
int d = 1;
for (int j = i+1; j < a.length; j++) {
if (a[i].equals(a[j])) {
d += 1;
p.add(j);
}
}
System.out.println("Count of "+a[i]+" is:"+d);
}
}
package naresh.java;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class StringWordDuplicates {
static void duplicate(String inputString){
HashMap<String, Integer> wordCount = new HashMap<String,Integer>();
String[] words = inputString.split(" ");
for(String word : words){
if(wordCount.containsKey(word)){
wordCount.put(word, wordCount.get(word)+1);
}
else{
wordCount.put(word, 1);
}
}
//Extracting of all keys of word count
Set<String> wordsInString = wordCount.keySet();
for(String word : wordsInString){
if(wordCount.get(word)>1){
System.out.println(word+":"+wordCount.get(word));
}
}
}
public static void main(String args[]){
duplicate("I am Java Programmer and IT Server Programmer with Java as Best Java lover");
}
}
class find
{
public static void main(String nm,String w)
{
int l,i;
int c=0;
l=nm.length();String b="";
for(i=0;i<l;i++)
{
char d=nm.charAt(i);
if(d!=' ')
{
b=b+d;
}
if(d==' ')
{
if(b.compareTo(w)==0)
{
c++;
}
b="";
}
}
System.out.println(c);
}
}
public class wordFrequency {
private static Scanner scn;
public static void countwords(String sent) {
sent = sent.toLowerCase().replaceAll("[^a-z ]", "");
ArrayList<String> arr = new ArrayList<String>();
String[] sentarr = sent.split(" ");
Map<String, Integer> a = new HashMap<String, Integer>();
for (String word : sentarr) {
arr.add(word);
}
for (String word : arr) {
int count = Collections.frequency(arr, word);
a.put(word, count);
}
for (String key : a.keySet()) {
System.out.println(key + " = " + a.get(key));
}
}
public static void main(String[] args) {
scn = new Scanner(System.in);
System.out.println("Enter sentence:");
String inp = scn.nextLine();
countwords(inp);
}
}
Determine the frequency of words in a file.
File f = new File(fileName);
Scanner s = new Scanner(f);
Map<String, Integer> counts =
new Map<String, Integer>();
while( s.hasNext() ){
String word = s.next();
if( !counts.containsKey( word ) )
counts.put( word, 1 );
else
counts.put( word,
counts.get(word) + 1 );
}
The following program finds the frequency, sorts it accordingly, and prints it.
Below is the output grouped by frequency:
0-10:
The 2
Is 4
11-20:
Have 13
Done 15
Here is my program:
package com.company;
import java.io.*;
import java.util.*;
import java.lang.*;
/**
* Created by ayush on 12/3/17.
*/
public class Linked {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Enter the sentence");
String st = br.readLine();
st=st.trim();
st = st + " ";
int count = lengthx(st);
System.out.println(count);
String arr[] = new String[count];
int p = 0;
int c = 0;
for (int i = 0; i < st.length(); i++) {
if (st.charAt(i) == ' ') {
arr[p] = st.substring(c,i);
System.out.println(arr[p]);
c = i + 1;
p++;
}
}
Map<String, Integer> map = new HashMap<>();
for (String w : arr) {
Integer n = map.get(w);
n = (n == null) ? 1 : ++n;
map.put(w, n);
}
for (String key : map.keySet()) {
System.out.println(key + " = " + map.get(key));
}
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Comparator<Map.Entry<String, Integer>> valueComparator = new Comparator<Map.Entry<String,Integer>>() {
#Override
public int compare(Map.Entry<String, Integer> e1, Map.Entry<String, Integer> e2) {
Integer v1 = e1.getValue();
Integer v2 = e2.getValue();
return v1.compareTo(v2); }
};
List<Map.Entry<String, Integer>> listOfEntries = new ArrayList<Map.Entry<String, Integer>>(entries);
Collections.sort(listOfEntries, valueComparator);
LinkedHashMap<String, Integer> sortedByValue = new LinkedHashMap<String, Integer>(listOfEntries.size());
for(Map.Entry<String, Integer> entry : listOfEntries){
sortedByValue.put(entry.getKey(), entry.getValue());
}
for(Map.Entry<String, Integer> entry : listOfEntries){
sortedByValue.put(entry.getKey(), entry.getValue());
}
System.out.println("HashMap after sorting entries by values ");
Set<Map.Entry<String, Integer>> entrySetSortedByValue = sortedByValue.entrySet();
for(Map.Entry<String, Integer> mapping : entrySetSortedByValue){
System.out.println(mapping.getKey() + " ==> " + mapping.getValue());
}
}
static int lengthx(String a) {
int count = 0;
for (int j = 0; j < a.length(); j++) {
if (a.charAt(j) == ' ') {
count++;
}
}
return count;
}
}
import java.io.*;
class Linked {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("Enter the sentence");
String st = br.readLine();
st = st + " ";
int a = lengthx(st);
String arr[] = new String[a];
int p = 0;
int c = 0;
for (int j = 0; j < st.length(); j++) {
if (st.charAt(j) == ' ') {
arr[p++] = st.substring(c,j);
c = j + 1;
}
}
}
static int lengthx(String a) {
int p = 0;
for (int j = 0; j < a.length(); j++) {
if (a.charAt(j) == ' ') {
p++;
}
}
return p;
}
}
Simply use Java 8 Stream collectors groupby function:
import java.util.function.Function;
import java.util.stream.Collectors;
static String[] COUNTRY_NAMES
= { "China", "Australia", "India", "USA", "USSR", "UK", "China",
"France", "Poland", "Austria", "India", "USA", "Egypt", "China" };
Map<String, Long> result = Stream.of(COUNTRY_NAMES).collect(
Collectors.groupingBy(Function.identity(), Collectors.counting()));
Count frequency of elements of list in java 8
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list,3,6,3,8,4,9,3,6,9,4,8,3,7,2);
Map<Integer, Long> frequencyMap = list.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
System.out.println(frequencyMap);
Note :
For String frequency counting split the string and convert it to list and use streams for count frequency => (Map frequencyMap)*
Check below link
String s[]=st.split(" ");
String sf[]=new String[s.length];
int count[]=new int[s.length];
sf[0]=s[0];
int j=1;
count[0]=1;
for(int i=1;i<s.length;i++)
{
int t=j-1;
while(t>=0)
{
if(s[i].equals(sf[t]))
{
count[t]++;
break;
}
t--;
}
if(t<0)
{
sf[j]=s[i];
count[j]++;
j++;
}
}
Created a simple easy to understand solution for this problem covers all test cases-
import java.util.HashMap;
import java.util.Map;
/*
* Problem Statement - Count Frequency of each word in a given string, ignoring special characters and space
* Input 1 - "To be or Not to be"
* Output 1 - to(2 times), be(2 times), or(1 time), not(1 time)
*
* Input 2 -"Star 123 ### 123 star"
* Output - Star(2 times), 123(2 times)
*/
public class FrequencyofWords {
public static void main(String[] args) {
String s1="To be or not **** to be! is all i ask for";
fnFrequencyofWords(s1);
}
//-------Supporting Function-----------------
static void fnFrequencyofWords(String s1) {
//------- Convert String to proper format----
s1=s1.replaceAll("[^A-Za-z0-9\\s]","");
s1=s1.replaceAll(" +"," ");
s1=s1.toLowerCase();
//-------Create String to an array with words------
String[] s2=s1.split(" ");
System.out.println(s1);
//-------- Create a HashMap to store each word and its count--
Map <String , Integer> map=new HashMap<String, Integer>();
for(int i=0;i<s2.length;i++) {
if(map.containsKey(s2[i])) //---- Verify if Word Already Exits---
{
map.put(s2[i], 1+ map.get(s2[i])); //-- Increment value by 1 if word already exits--
}
else {
map.put(s2[i], 1); // --- Add Word to map and set value as 1 if it does not exist in map--
}
}
System.out.println(map); //--- Print the HashMap with Key, Value Pair-------
}
}
public class WordFrequencyProblem {
public static void main(String args[]){
String s="the quick brown fox jumps fox fox over the lazy dog brown";
String alreadyProcessedWords="";
boolean isCount=false;
String[] splitWord = s.split("\\s|\\.");
for(int i=0;i<splitWord.length;i++){
String word = splitWord[i];
int count = 0;
isCount=false;
if(!alreadyProcessedWords.contains(word)){
for(int j=0;j<splitWord.length;j++){
if(word.equals(splitWord[j])){
count++;
isCount = true;
alreadyProcessedWords=alreadyProcessedWords+word+" ";
}
}
}
if(isCount)
System.out.println(word +"Present "+ count);
}
}
}
public class TestSplit {
public static void main(String[] args) {
String input="Find the repeated word which is repeated in this string";
List<String> output= (List) Arrays.asList(input.split(" "));
for(String str: output) {
int occurrences = Collections.frequency(output, str);
System.out.println("Occurence of " + str+ " is "+occurrences);
}
System.out.println(output);
}
}
Please try these it may be help for you
public static void main(String[] args) {
String str1="I am indian , I am proud to be indian proud.";
Map<String,Integer> map=findFrquenciesInString(str1);
System.out.println(map);
}
private static Map<String,Integer> findFrquenciesInString(String str1) {
String[] strArr=str1.split(" ");
Map<String,Integer> map=new HashMap<>();
for(int i=0;i<strArr.length;i++) {
int count=1;
for(int j=i+1;j<strArr.length;j++) {
if(strArr[i].equals(strArr[j]) && strArr[i]!="-1") {
strArr[j]="-1";
count++;
}
}
if(count>1 && strArr[i]!="-1") {
map.put(strArr[i], count);
strArr[i]="-1";
}
}
return map;
}
try this
public void count()throws IOException
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("enetr the strring");
String s = in.readLine();
int l = s.length();
int a=0,b=0,c=0,i,j,y=0;
char d;
String x;
String n[] = new String [50];
int m[] = new int [50];
for (i=0;i<50;i++)
{
m[i]=0;
}
for (i=0;i<l;i++)
{
d = s.charAt(i);
if((d==' ')||(d=='.'))
{
x = s.substring(a,i);
a= i+1;
for(j=0;j<b;j++)
{
if(x.equalsIgnoreCase(n[j]) == true)
{
m[j]++;
c = 1;
}
}
if(c==0)
{
n[b] = x;
m[b] = 1;
b++;
}
}
c=0;
}
for(i=0;i<b;i++)
{
for (j=0;j<b;j++)
{
if(y<m[j])
{
y=m[j];
}
}
if(m[i]==y)
{
System.out.println(n[i] + " : " + m[i]);
m[i]=0;
}
y=0;
}
}

Sort integer array into decreasing order of frequency

I need to take a string from a jTextFrame then sort it into order of occurence and then print it out. eg. babablackbike return: bbbbaaakkceil
String word = (String)jTextField1.getText();
String indexes = "abcdefghijklmnopqrstuvwxyz";
int[] count = new int[indexes.length()];
for (int i = 0; i < word.length(); i++)
{
int index = indexes.indexOf(word.charAt(i));
if (index < 0)
continue;
count[index]++;
}
for (int j = 0; j < count.length; j++)
{
if (count[j] < 1)
continue;
char[] indiv = indexes.toCharArray();
for (int p = 0; p < count[j];p++)
{
jTextArea1.append(""+indiv[j]);
System.out.println(indiv[(j)] +"="+ count[j] + p);
}
}
You first need to get counts of each character in your input:
final String in = "babablackbike";
final Map<Character, Integer> counts = new HashMap<>();
final List<Character> inList = new ArrayList<>();
for (final char c : in.toCharArray()) {
Integer count = counts.get(c);
if (count == null) {
counts.put(c, 1);
} else {
counts.put(c, count + 1);
}
inList.add(c);
}
As Java is a bit peculiar with char[] versus Character[] - there is no way to sort primitives with a custom comparator due to generics not working with primitives - I also build a List<Character> at the same time.
Now we just need to sort the List<Character> using a custom Comparator and the information in the Map counts:
Collections.sort(inList, new Comparator<Character>() {
#Override
public int compare(final Character o1, final Character o2) {
int c = counts.get(o1).compareTo(counts.get(o2));
if (c != 0) {
return -c;
}
return o1.compareTo(o2);
}
});
So first we sort by the count of the character in the input (reverse order) and then we sort by the characters themselves.
Now we simply need to build the List back into a String:
final StringBuilder outBuilder = new StringBuilder();
for (final Character c : inList) {
outBuilder.append(c);
}
System.out.println(outBuilder.toString());
Output:
bbbbaaakkceil
I think that, the best solution it would be to create a HashMap like this
Map<Character, Integer> quantity = new HashMap<Character, Integer>();
Then, you can do a loop like this:
for (int i = 0; i < str.length() - 1; i++) {
char c = str.charAt(i);
// increment value of c in quantity map
}
After that, you can sort it by value and easily print.
Here is the general algorithm:
Map each character in the string to the number of times it appears in it.
Sort the map keys (characters) by decreasing order of their values (count).
Print each character according to the number of times it appears in the string.
And here is a coding example:
public void Print(String string)
{
HashMap<Character,Integer> hashMap = new HashMap<Character,Integer>();
TreeMap<Character,Integer> treeMap = new TreeMap<Character,Integer>(new ValueComparator(hashMap));
for (Character key : string.toCharArray())
{
Integer value = hashMap.get(key);
if (value == null)
hashMap.put(key,1);
else
hashMap.put(key,value+1);
}
treeMap.putAll(hashMap);
for (Character key : treeMap.keySet())
{
Integer value = hashMap.get(key);
for (Integer i=0; i<value; i++)
System.out.print(key);
}
}
private class ValueComparator implements Comparator<Character>
{
Map<Character,Integer> base;
public ValueComparator(Map<Character,Integer> base)
{
this.base = base;
}
public int compare(Character a,Character b)
{
if (base.get(a) >= base.get(b))
return -1;
else
return +1;
}
}

Categories