Frequency of elements in an ArrayList - java

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);
}

Related

How can I get the count of most duplicated value in a list after sorting it alphabetically?

What is the easiest way to get the most duplicated value in a list and sorted in descending order...
for example:
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
`
"renault" & "rexon" are most duplicated and if sorted in descending order alphabetically I would like to get the rexon.
I think one of the most readable and elegant way would be to use the Streams API
strings.stream()
.collect(Collectors.groupingBy(x -> x, Collectors.counting()))
.entrySet().stream()
.max(Comparator.comparingLong((ToLongFunction<Map.Entry<String, Long>>) Map.Entry::getValue).thenComparing(Map.Entry::getKey))
.map(Map.Entry::getKey)
.ifPresent(System.out::println);
Create a map of names with their corresponding number of occurrences.
Get names and sort them in descending order.
Print the first name that has the highest number of occurrences.
class Scratch {
public static void main(String[] args) {
List<String> list = List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon");
Map<String, Integer> duplicates = new HashMap<>();
// 1. Create a map of names with their corresponding
// number of occurrences.
for (String s: list) {
duplicates.merge(s, 1, Integer::sum);
}
// 2. Get names and sort them in descending order.
List<String> newList = new ArrayList<String>(duplicates.keySet());
newList.sort(Collections.reverseOrder());
// 3. Print the first name that has the highest number of
// occurrences.
Integer max = Collections.max(duplicates.values());
newList.stream().filter(name -> duplicates.get(name).equals(max))
.findFirst()
.ifPresent(System.out::println);
}
}
After some time this is what I came with (I only tested it with your example and it worked):
public class Duplicated {
public static String MostDuplicated(String[] a) {
int dup = 0;
int position = -1;
int maxDup = 0;
for(int i = 0; i < a.length; i++) { //for every position
for(int j = 0; j < a.length; j++){ //compare it to all
if(a[i].equals(a[j])) { dup++; } // and count how many time is duplicated
}
if (dup > maxDup) { maxDup = dup; position = i;}
//if the number of duplications
//is greater than the maximum you have got so far, save this position.
else if (dup == maxDup) {
if( a[i].compareTo(a[position]) > 0 ){ position = i; }
//if its the same, keep the position of the alphabetical last
// (if u want the alphabetical first, just change the "<" to ">")
}
}
return a[position]; //return the position you saved
}
}
You are asking to sort the list and then find the most common item.
I would suggest that the easiest way to sort the list is using the sort method that is built into list.
I would then suggest finding the most common by looping with the for..each construct, keeping track of the current and longest streaks.
I like Yassin Hajaj's answer with streams but I find this way easier to write and easier to read. Your mileage may vary, as this is subjective. :)
import java.util.*;
public class SortingAndMostCommonDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
list.sort(Comparator.reverseOrder());
System.out.println(list);
System.out.println("The most common is " + mostCommon(list) + ".");
}
private static String mostCommon(List<String> list) {
String mostCommon = null;
int longestStreak = 0;
String previous = null;
int currentStreak = 0;
for (String s : list) {
currentStreak = 1 + (s.equals(previous) ? currentStreak : 0);
if (currentStreak > longestStreak) {
mostCommon = s;
longestStreak = currentStreak;
}
previous = s;
}
return mostCommon;
}
}
The fast algorithm takes advantage of the fact that the list is sorted and finds the list with the most duplicates in O(n), with n being the size of the list. Since the list is sorted the duplicates will be together in consecutive positions:
private static String getMostDuplicates(List<String> list) {
if(!list.isEmpty()) {
list.sort(Comparator.reverseOrder());
String prev = list.get(0);
String found_max = prev;
int max_dup = 1;
int curr_max_dup = 0;
for (String s : list) {
if (!s.equals(prev)) {
if (curr_max_dup > max_dup) {
max_dup = curr_max_dup;
found_max = prev;
}
curr_max_dup = 0;
}
curr_max_dup++;
prev = s;
}
return found_max;
}
return "";
}
Explanation:
We iterate through the list and keep track of the maximum of duplicates found so far and the previous element. If the current element is the same as the previous one we increment the number of duplicates found so far. Otherwise, we check if the number of duplicates is the bigger than the previous maximum of duplicates found. If it is we update accordingly
A complete running example:
public class Duplicates {
private static String getMostDuplicates(List<String> list) {
if(!list.isEmpty()) {
list.sort(Comparator.reverseOrder());
String prev = list.get(0);
String found_max = prev;
int max_dup = 1;
int curr_max_dup = 0;
for (String s : list) {
if (!s.equals(prev)) {
if (curr_max_dup > max_dup) {
max_dup = curr_max_dup;
found_max = prev;
}
curr_max_dup = 0;
}
curr_max_dup++;
prev = s;
}
return found_max;
}
return "";
}
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault","BMW","Renault","Renault","Toyota","Rexon","BMW","Opel","Rexon","Rexon"));
String duplicates = getMostDuplicates(list);
System.out.println("----- Test 1 -----");
System.out.println(duplicates);
list = new ArrayList<>(List.of("Renault","BMW"));
duplicates = getMostDuplicates(list);
System.out.println("----- Test 2 -----");
System.out.println(duplicates);
list = new ArrayList<>(List.of("Renault"));
duplicates = getMostDuplicates(list);
System.out.println("----- Test 3 -----");
System.out.println(duplicates);
}
}
Output:
----- Test 1 -----
Rexon
----- Test 2 -----
Renault
----- Test 3 -----
Renault
Actually, I found a solution which works:
public static void main(String[] args) {
List<String> list = new ArrayList<>(List.of("Renault", "BMW", "BMW", "Renault", "Renault", "Toyota",
"Rexon", "BMW", "Opel", "Rexon", "Rexon"));
Map<String, Integer> soldProducts = new HashMap<>();
for (String s : list) {
soldProducts.put(s, soldProducts.getOrDefault(s, 0) + 1);
}
LinkedHashMap<String, Integer> sortedMap = soldProducts.entrySet()
.stream()
.sorted(VALUE_COMPARATOR.thenComparing(KEY_COMPARATOR_REVERSED))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
String result = "";
for (Map.Entry<String, Integer> s : sortedMap.entrySet()) {
result = s.getKey();
}
System.out.println(result);
}
static final Comparator<Map.Entry<String, Integer>> KEY_COMPARATOR_REVERSED =
Map.Entry.comparingByKey(Comparator.naturalOrder());
static final Comparator<Map.Entry<String, Integer>> VALUE_COMPARATOR =
Map.Entry.comparingByValue();

How to deal with multiplicity when checking if an arraylist is a subset

I have two Arraylist and I want to check if one is a subset of the other (ordering is not important in the comparison).
The problem is: Lets say Ar1={e,e,r} and Ar2={e,r,b,d}. In my code it says Ar1 is a subset. But I want it to say false, cause Ar2 has only one e. How to do that?
public static void dostuff(String word1,String word2){
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
for (String character : word1.split("")) {
list1.add(character);
}
for (String character : word2.split("")) {
list2.add(character);
}
boolean sub = list1.containsAll(list2) || list2.containsAll(list1);
System.out.println(sub);
}
I think this may be what you want. Note that list2.remove(elem) returns true if an element was removed, and false if not.
public static boolean dostuff(String word1,String word2){
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3;
for (String character : word1.split("")) {
list1.add(character);
}
for (String character : word2.split("")) {
list2.add(character);
}
list3 = new ArrayList<>(list2);
boolean isSubset = true;
for (final String elem : list1) {
if (!list2.remove(elem)) {
isSubset = false;
break;
}
}
if (isSubset) {
return true;
}
for (final String elem : list3) {
if (!list1.remove(elem)) {
return false;
}
}
return true;
}
#Johdoe. The below logic may help you. you can optimize if you want.
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
list1.add("e");
list1.add("a");
list1.add("r");
list2.add("e");
list2.add("r");
list2.add("b");
list2.add("d");
list2.add("a");
System.out.println("list2 " + list2);
System.out.println("list1 " + list1);
Set<Integer> tempList = new HashSet<Integer>();
System.out.println(" containsAll " + list2.containsAll(list1));
for (int i = 0; i < list2.size(); i++) {
for (int j = 0; j < list1.size(); j++) {
if (list2.get(i).equals(list1.get(j))) {
tempList.add(i);
}
}
}
System.out.println(" tempList " + tempList);
System.out.println("list 1 is subset of list 2 "
+ (tempList.size() == list1.size()));
Note also that a mathematical, and java, set is unique, so be careful of using the term "subset".
You can use a frequency map to test if one list "has each element in another list, with the same or fewer occurrences". i.e. once you have your list you can convert it into a Map<T, Integer> to store the counts of each list element. The use of a map avoids mutating the original lists (which you would do if testing by removing elements from the master list as you encounter them):
public static <T> boolean isSublist(List<T> masterList, List<T> subList) {
Map<T, Integer> masterMap = new HashMap<T, Integer>();
for (T t : masterList) masterMap.put(t, 1 + masterMap.getOrDefault(t, 0));
Map<T, Integer> testMap = new HashMap<T, Integer>();
for (T t : subList) testMap.put(t, 1 + testMap.getOrDefault(t, 0));
for(Map.Entry<T, Integer> entry : testMap.entrySet()) {
if (masterMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) return false;
}
return true;
}
getOrDefault is only available as of Java 8, but you can easily write your own method to take care of the same operation.
I have found a solution myself, please check of this is right, but i believe it is.
public static void dostuff(String word1, String word2) {
boolean sub = false;
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();
ArrayList<String> list3 = new ArrayList<String>();
for (int i = 0; i < word1.length(); i++) {
list1.add(word1.split("")[i]);
}
for (int i = 0; i < word2.length(); i++) {
list2.add(word2.split("")[i]);
}
if (list1.size() >= list2.size()) {
for (String i : list2) {
if (list1.contains(i)) {
list1.remove(i);
list3.add(i);
}
}
if (list2.containsAll(list3) && list2.size() == list3.size()) {
sub = true;
}
} else if (list2.size() > list1.size()) {
for (String i : list1) {
if (list2.contains(i)) {
list2.remove(i);
list3.add(i);
}
if (list1.containsAll(list3) && list1.size() == list3.size()) {
sub = true;
}
}
}
System.out.println(sub);
}
You could use a couple of maps to store the frequency of each letter:
public static void dostuff(String word1, String word2) {
Map<String, Long> freq1 = Arrays.stream(word1.split("")).collect(
Collectors.groupingBy(Function.identity(), Collectors.counting()));
Map<String, Long> freq2 = Arrays.stream(word2.split("")).collect(
Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(contains(freq1, freq2) || contains(freq2, freq1));
}
Where the contains method would be as follows:
private static boolean contains(Map<String, Long> freq1, Map<String, Long> freq2) {
return freq1.entrySet().stream().allMatch(
e1 -> e1.getValue().equals(freq2.get(e1.getKey())));
}
Test:
dostuff("eer", "erbd"); // {r=1, e=2}, {b=1, r=1, d=1, e=1}, false
dostuff("erbed", "eer"); // {b=1, r=1, d=1, e=2}, {r=1, e=2}, true
The idea is to use java 8 streams to create the frequencies map, and then, stream the entry set of both maps to compare all the elements and their frequencies. If all entries match, then it means that the second list contains all the elements of the first list with the same frequencies, regardless of the order.
In case the result is false for the first list, the check is performed the other way round as well, as per the question requirements.
Now that I understand that the order of the contents doesn't matter, you just want to know if all the characters of one string exists in another (with the same frequency) or vice versa.
Try this function, it'll check everything without having to call the method twice and without using streams:
public static boolean subsetExists(String s1, String s2) {
String temp = s2.replaceAll(String.format("[^%s]", s1), "");
char[] arr1 = s1.toCharArray();
char[] arr2 = temp.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
boolean isSubset = new String(arr2).contains(new String(arr1));
if (!isSubset) {
temp = s1.replaceAll(String.format("[^%s]", s2), "");
arr1 = temp.toCharArray();
arr2 = s2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
isSubset = new String(arr1).contains(new String(arr2));
}
return isSubset;
}
You don't have to bother turning your Strings into Lists. What's happening is we're checking if all the letters in s1 exist in s2 or vice versa.
We removed characters that are not in s1 from s2 and stored that result in a temporary String. Converted both the temporary String and s1 into char[]s. We then sort both arrays and convert them back into Strings. We then can check if NEW SORTED temporary String contains() the NEW SORTED s1. If this result is false, then we apply the same logical check from s2 to s1.
Usage:
public static void main(String[] args) throws Exception {
String s1 = "eer";
String s2 = "bderz";
String s3 = "bderzzeee";
System.out.println(subsetExists(s1, s2));
System.out.println(subsetExists(s1, s3));
}
public static boolean subsetExists(String s1, String s2) {
String temp = s2.replaceAll(String.format("[^%s]", s1), "");
char[] arr1 = s1.toCharArray();
char[] arr2 = temp.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
boolean isSubset = new String(arr2).contains(new String(arr1));
if (!isSubset) {
temp = s1.replaceAll(String.format("[^%s]", s2), "");
arr1 = temp.toCharArray();
arr2 = s2.toCharArray();
Arrays.sort(arr1);
Arrays.sort(arr2);
isSubset = new String(arr1).contains(new String(arr2));
}
return isSubset;
}
Results:
false
true
Here is a Working Solution
Check Demo
public static void main (String[] args) throws java.lang.Exception
{
dostuff("eer","erbd");
}
public static void dostuff(String word1, String word2) {
List<String> list1 = new ArrayList<String>();
for (String character : word1.split("")) {
list1.add(character);
}
boolean sub = true;
for (String character : word2.split("")) {
if (list1.remove(character)) {
if (list1.isEmpty()) {
break;
}
} else {
sub = false;
break;
}
}
System.out.println(sub);
}

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;
}
}

How to iterate through two dimensional ArrayList using iterator?

I would like to iterate through two dimensional ArrayList which includes String objects using iterator. I also would like to iterate in a way that let me choose whether I want to iterate horizontally(row) first or vertically(column) by using a boolean value. How can I implement this in java?
What I've tried so far.
public class IterateThis implements Iterator<String>{
ArrayList<ArrayList<String>> array;
public IterateThis(){
array = new ArrayList<ArrayList<String>>();
array.add(new ArrayList<String>());
array.add(new ArrayList<String>());
array.add(new ArrayList<String>());
array.get(0).add("1");
array.get(0).add("2");
array.get(0).add("2");
array.get(1).add("4");
array.get(1).add("5");
array.get(1).add("6");
}
Iterator<String> it = array.iterator(); //This gives me an error...why?
I don't know how I can implement the boolean value though.
Maybe you need to implement two versions, with a boolean that decides which loop to use:
public void iterate(boolean horizantalFirst){
if(horizontalFirst){
for(int i=0; i<array.size(); i++){ // first iterate through the "outer list"
for(int j=0; j<array.get(i).size(); j++){ // then iterate through all the "inner lists"
array.get(i).get(j)="1";
}
}
}else{
int j=0; // index to iterate through the "inner lists"
for(; j<array.get(j).size(); j++){ //dangerous, you need to be sure that there is a j-th element in array
for(int i=0; i<array.size(); i++){ // iterate here through the outer list, by always working on the j-th element
array.get(i).get(j)="1";
}
}
}
}
Why not try this:
import java.util.ArrayList;
public class Iteration
{
private ArrayList<ArrayList<String>> array;
public Iteration()
{
array = new ArrayList<>();
array.add(new ArrayList<String>());
array.get(0).add("000");
array.get(0).add("001");
array.get(0).add("010");
array.add(new ArrayList<String>());
array.get(1).add("100");
array.get(1).add("101");
array.get(1).add("110");
array.get(1).add("111");
iterateRowWise();
System.out.println("\n\n");
iterateColumnWise();
}
public void iterateRowWise()
{
// This uses iterator behind the scene.
for (ArrayList<String> row : array)
{
for (String element : row)
{
System.out.print(element + " ");
}
System.out.println();
}
}
public void iterateColumnWise()
{
int arraySize = array.size();
int maxColumns = getMaximumListSize();
for (int c = 0; c < maxColumns; c++)
{
for (int r = 0; r < arraySize; r++)
{
ArrayList<String> rowList = array.get(r);
if (c < rowList.size())
{
System.out.print(rowList.get(c) + " ");
}
}
System.out.println();
}
}
private int getMaximumListSize()
{
int maxListSize = 0;
for (ArrayList<String> rowList : array)
{
if (maxListSize < rowList.size())
maxListSize = rowList.size();
}
return maxListSize;
}
public static void main(String[] args)
{
new Iteration();
}
}
The iterateRowWise() method iterates using the iterator, but it does so behind the scene.
The iterateColumnWise() method doesn't use iterator, but its safe to use.
Row-wise iteration is simple as shown in the #Awfully Awesome answer.
Tried a columnwise iteration with assumption that List will always have m cross n elements where m=n
public static void IterateThis() {
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
array.add(new ArrayList<String>());
array.add(new ArrayList<String>());
array.get(0).add("1");
array.get(0).add("2");
array.get(0).add("2");
array.get(1).add("4");
array.get(1).add("5");
array.get(1).add("6");
Iterator<ArrayList<String>> it = array.iterator();
int topLevelIteratorResetCounter = 0;
int noOfIteratorNextRequired = 1;
int size = array.size();
while (it.hasNext()) {
ArrayList<String> strList = it.next();
if (noOfIteratorNextRequired > strList.size())
break;
Iterator<String> itString = strList.iterator();
int numtimes = 0;
String str = null;
while (numtimes != noOfIteratorNextRequired) {
str = itString.next();
numtimes++;
}
System.out.println(str);
numtimes = 0;
topLevelIteratorResetCounter++;
if (topLevelIteratorResetCounter == size) { //as column count is equal to column size
it = array.iterator(); //reset the iterator
noOfIteratorNextRequired++;
topLevelIteratorResetCounter = 0;
}
}
}
The answer uses Iterator.

How to count frequency of characters in a string?

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;
}

Categories