Printing out a TreeMap<String, TreeSet<String>> Key and Mapped Values - java

I have a TreeMap <String, TreeSet <String>>
{Heat = [Bosh, Lebron, Wade], Nets =[DWill, KG], Sonics = null, Warriors = [Curry,Iggy,Thompson]}
and I want to print out.
Heat Bosh Lebron Wade
Nets DWill KG
Sonics
Warriors Curry Iggy Thompson
I've tried
for ( String w : listNBA){
System.out.print( w + " ");
if (treemap.containsKey(w))
System.out.println(treemap.get(w));
else
System.out.println( "" ); // print nothing if team doesn't exist
But this isn't quite right either, and it's output is...
Heat [Bosh, Lebron, Wade]
Nets [DWill, KG]
Sonics null
Warriors [Curry,Iggy,Thompson]
So, my question is: Is there any easy way to convert a TreeSet to a String in my print method?

You can do something like this :
StringBuilder stringBuilder = new StringBuilder();
for (Entry<String, TreeSet<String>> mapEntry : treemap.entrySet()) {
stringBuilder.append(mapEntry.getKey());
if (mapEntry.getValue() != null) {
for (String setEntry : mapEntry.getValue()) {
stringBuilder.append(" ").append(setEntry);
}
}
stringBuilder.append("\n");
}
System.out.println(stringBuilder.toString());

Java 8 has a String.join method that works great for this:
for ( String w : listNBA){
System.out.print( w + " ");
if (treemap.containsKey(w) && treemap.get(w) != null)
System.out.println(String.join(" ",treemap.get(w)));
else
System.out.println( "" ); // print nothing if team doesn't exist
}
Note that while your original System.out.println(treemap.get(w)) printed out null if the get method returned null, String.join will throw a NullPointerException if it gets a null parameter. Thus, I've added a null check to the previous if.
join's first parameter is a string that will be inserted between each input string. It can either take a variable number of String (or any other CharSequence) arguments, or an array of String (or other CharSequence).

You can iterate through the entry set and print out the key and the corresponsing value.
for(Map.Entry<String, TreeSet <String>> entry : treemap.entrySet())
{
System.out.print( entry.getKey() + " ");
System.out.print( entry.getValue());
}

Related

Returning occurrences of a character in a string

I've got a task where I'm to discover how many times 'A', 'C', 'G' and 'T' occur in a string, and return it in the following format:
A:count C:count G:count T:count
I'm very new to Java having started learning Java 3 days ago I've come across literature referring to a HashMap being the most viable and efficient means of storing and retrieving this data - As such, I opted in this method.
I've managed to create the conditionals and store the data, however I'm struggling with the presentation of data as mentioned above.
Apologise for some offensive code in advance, what I have so far is:
public class DNA {
static void characterCount(String dna) {
HashMap<Character, Integer> charCountMap = new HashMap<Character, Integer>();
char[] dnaArray = dna.toCharArray();
charCountMap.put('C', 0);
charCountMap.put('A', 0);
charCountMap.put('G', 0);
charCountMap.put('T', 0);
for (char q : dnaArray) {
if (q == 'A' || q == 'C' || q == 'G' || q == 'T') {
charCountMap.put(q, charCountMap.get(q) + 1);
} else {
continue;
}
}
System.out.println(charCountMap);
}
public static void main(String[] args) {
characterCount("ACTGSRSSDSGGGHHTYTCCCFDT");
}
}
I would appreciate any input, advice or signposting to relevant resources for further learning.
Thank you very much for your time!
One way to get the required output is by doing this:
String output = charCountMap.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getKey() + ":" + entry.getValue())
.collect(Collectors.joining(" "));
System.out.println(output);
You just need to add the below code for that formatting instead of System.out.println(charCountMap);:
for (Entry<Character, Integer> c : charCountMap.entrySet()) {
System.out.print(c.getKey()+ ":" + c.getValue() + " ");
}
So you will get output like this
A:1 C:4 T:4 G:4
Use "LinkedHashMap" instead of "HashMap" if you want to follow the character sequence.
tl;dr
Generate output using String.format. The %d is a placeholder for a long primitive value produced from our passed Long object via auto-boxing.
String.format(
"C:%d A:%d G:%d T:%d" ,
map.get( "C" ) , map.get( "A" ) , map.get( "G" ) , map.get( "T" )
)
Details
Streams makes easier work of this.
Here is a modified version of code from this article.
The split method returns an array of String objects.
We convert those to uppercase. You could omit this step if you know your inputs to already be in uppercase.
We then filter out any strings that are not our desired CAGT.
Lastly, we use a Collector to get a count of each letter, and store the result in a new map.
String input = "ACTGSRSSDSGGGHHTYTCCCFDT" ;
Map < String , Long > map =
Arrays
.stream(
input.split("")
)
.map( String :: toUpperCase )
.filter( s -> "CAGT".contains( s ) )
.collect(
Collectors.groupingBy(
s -> s , TreeMap :: new , Collectors.counting()
)
)
;
Generate output.
String output =String.format( "C:%d A:%d G:%d T:%d" , map.get( "C" ) , map.get( "A" ) , map.get( "G" ) , map.get( "T" ) ) ;
System.out.println( output ) ;
See this code run live at Ideone.com.
C:4 A:1 G:4 T:4
A possible solution is use an int array and map the character A-T to an index. The array size is the number of characters from A to T. The index 0 maps to A and the index 19 maps to T.
static void characterCount(String dna) {
int[] a = new int[20];
for(char c: dna.toCharArray()){
int i = c-'A';
if (i <= 19) a[i]++;
}
System.out.printf("A:%d C:%d G:%d T:%d\n", a[0],a[2],a[6],a[19]);
}
You may concide upper and lower case charachter as well and decide wether "a" is same or different to "A".
If the same, you can change your code to
char[] dnaArray = dna.toUpperCase().toCharArray();
You might also want to make the logic more stable and check, whether the input string is valid
HashMap<Character, Integer> charCountMap = new HashMap<Character, Integer>();
if (dna == null || dna.isEmpty()) {
return;
}
char[] dnaArray = dna.toUpperCase().toCharArray();
Beside this, you could also start cuonting the hole alphabet and use the int value of the corresponding char.
HashMap<Character, Integer> charCountMap = new HashMap<Character, Integer>();
if (dna == null || dna.isEmpty()) {
return;
}
char[] dnaArray = dna.toUpperCase().toCharArray();
for (char q : dnaArray) {
for (int charachter = 'A'; charachter <= 'Z'; ++charachter) {
if (q == charachter) {
charCountMap.put(q, charCountMap.getOrDefault(q, 0) + 1);
break;
}
}
}
System.out.println(charCountMap);
Output:
{A=1, R=1, C=4, S=4, T=4, D=2, F=1, G=4, H=2, Y=1}
EDIT
Use a TreeMap to sort the map entries
TreeMap<Character, Integer> charCountMap = new TreeMap<Character, Integer>();
Output:
{A=1, C=4, D=2, F=1, G=4, H=2, R=1, S=4, T=4, Y=1}

How can I use a string array as key in hash map?

I've made an String array out of a .txt and now want to make a HashMap with this string as key. But I don't want to have the String as one key to one value, I want to have each Information as a new key for the HashMap.
private static String[] readAndConvertInputFile() {
String str = StdIn.readAll();
String conv = str.replaceAll("\'s", "").replaceAll("[;,?.:*/\\-_()\"\'\n]", " ").replaceAll(" {2,}", " ").toLowerCase();
return conv.split(" "); }
So the information in the string is like ("word", "thing", "etc.", "pp.", "thing").
My value should be the frequency of the word in the text. So for example key: "word" value: 1, key: "thing" value: 2 and so on... I'm clueless and would be grateful if someone could help me, at least with the key. :)
You can create a Map while using the String value at each array index as the key, and an Integer as the value to keep track of how many times a word appeared.
Map<String,Integer> map = new HashMap<String,Integer>();
Then when you want to increment, you can check if the Map already contains the key, if it does, increase it by 1, otherwise, set it to 1.
if (occurences.containsKey(word)) {
occurences.put(word, occurences.get(word) + 1);
} else {
occurences.put(word, 1);
}
So, while you are looping over your string array, convert the String to lower case (if you want to ignore case for word occurrences), and increment the map using the if statement above.
for (String word : words) {
word = word.toLowerCase(); // remove if you want case sensitivity
if (occurences.containsKey(word)) {
occurences.put(word, occurences.get(word) + 1);
} else {
occurences.put(word, 1);
}
}
A full example is shown below. I converted to words to lowercase to ignore case when using the key in the map, if you want to keep case, remove the line where I convert it to lowercase.
public static void main(String[] args) {
String s = "This this the has dog cat fish the cat horse";
String[] words = s.split(" ");
Map<String, Integer> occurences = new HashMap<String, Integer>();
for (String word : words) {
word = word.toLowerCase(); // remove if you want case sensitivity
if (occurences.containsKey(word)) {
occurences.put(word, occurences.get(word) + 1);
} else {
occurences.put(word, 1);
}
}
for(Entry<String,Integer> en : occurences.entrySet()){
System.out.println("Word \"" + en.getKey() + "\" appeared " + en.getValue() + " times.");
}
}
Which will give me output:
Word "cat" appeared 2 times.
Word "fish" appeared 1 times.
Word "horse" appeared 1 times.
Word "the" appeared 2 times.
Word "dog" appeared 1 times.
Word "this" appeared 2 times.
Word "has" appeared 1 times.
Yes, you can use an array (regardless of element type) as a HashMap key.
No, shouldn't do so. The behavior is unlikely to be what you want (in general).
In your particular case, I don't see why you even propose using an array as a key in the first place. You seem to want Strings drawn from among your array elements as keys.
You could construct a word frequency table like so:
Map<String, Integer> computeFrequencies(String[] words) {
Map<String, Integer> frequencies = new HashMap<String, Integer>();
for (String word: words) {
Integer wordFrequency = frequencies.get(word);
frequencies.put(word,
(wordFrequency == null) ? 1 : (wordFrequency + 1));
}
return frequencies;
}
In java 8 using stream
String[] array=new String[]{"a","b","c","a"};
Map<String,Integer> map1=Arrays.stream(array).collect(Collectors.toMap(x->x,x->1,(key,value)->value+1));

How to get rid of null values from a String of array in java?

I am trying to remove duplicates from my list and then trying to save it in a String Array. However i want to eliminate if there is a empty value i.e. "" but my if condition does not seem to work it still display a blank in the output. How can i get rid of it ? I am expecting an overall size of 8 elements after ignoring the blank value
Output:Printing Set Peardonville and South Fraser
Printing Set Clearbrook and South Fraser
Printing Set George Ferguson and Gladwin
Printing Set Ar. Bourquin Exchange
Printing Set Lv. Bourquin Exchange
Printing Set Downtown Abbotsford
Printing Set Marshall and McCallum
Printing Set University of the Fraser Valley
**Printing Set**
Size of StopNamesForDB is = 9
Set<String> set = new LinkedHashSet<String>(StopNames);
System.out.println("Size of Set Object" + set.size());
StopNamesForDB = new String[set.size()];
for (String string : set) {
if(string.equals(" ")){
}
else{
System.out.println("Printing Set " + string);
StopNamesForDB[i] = string;
i++;
}
}
You are initializing array like:
String [] StopNamesForDB = new String[set.size()];
By doing this, size of StopNamesForDB array will always be 9, irrespective you add element to it or not.
Also, please note that you are checking for a space in your code:
if(string.equals(" ")){
Please change it to below code or trim it:
if(string.equals("")){
Thanks, hope this helps.
Use the trim method: if(string.trim().isEmpty())
In if condition, try this:
if ( string.trim().equals("") ){
}
else{
//Your code
}
Try this:
List<String> toRemove = new ArrayList<String>();
for (String string : set) {
if(string.isEmpty()){
toRemove.add(string);
}
}
then remove all the matched objects from your set.
for(String string: toRemove)
set.remove(string);
You are talking about List or Set.
Set does not allow duplicate values so do not worry about duplicates ...
If you want to filter " " use
if (string != null && string.trim().length() > 0){
}
Try the following, since you intent only to discard the empty ones.
for (String string : set) {
if (string != null && string.trim().length() > 0) {
System.out.println("Printing Set " + string);
StopNamesForDB[i] = string;
i++;
}
}
Update your codition
if(string.equals(" ")){
}
to
if(string.trim().length == 0){
}
it will work :)

Map entry key in java

I'm trying to debug a problem I've on a script, I'm newly to Java I think it's a simplest thing but I need to understand. This :
for( Map.Entry<String,int[]> entry : this.indexMap.entrySet())
{
if( !entry.getKey().equals("nickname"))
{
System.out.print("'"+ entry.getKey() +"' contains "+ entry.getKey().length() +" chars");
System.out.print("'"+ name +"' contains "+ name.length() +" chars");
}
else if( entry.getKey().trim().equals("nickname") )
{
System.out.print("Yes are sames");
}
}
For a String name = "nickname", displays me that :
18:56:15 [INFOS] 'nickname' contains 94 chars
18:56:15 [INFOS] 'nickname' contains 8 chars
I'm trying to understand this.
The problem is entry.getKey() returns the same thing as my string name, but not really the same. In first test, we saw the two vars are different, so the print is did, but the twos vars have the same value, and not the same length. In the else-if, I tried to remove spaces but not printed so where are from these 94 chars?
https://code.google.com/p/imdbparsers/source/browse/trunk/imdb+parsers/src/imdb/parsers/xmltosql/NamedParameterStatement.java?r=6
Is the code, methods concerned are
private String parse(String query)
private int[] getIndexes(String name)
line 161 et 89
This for loop i've in mine is only to debug the
int[] indexes = (int[]) indexMap.get(name);
Returns always null
The query string is :
SELECT COUNT(`account_id`) AS `total` FROM `game_accounts` WHERE `nickname`=:nickname
The difference between
entry.getKey().equals("nickname")
and
entry.getKey().trim().equals("nickname")
is trim().
The first take in account the spaces and the second not.
It's because they are a loop on a map: to find the 'bad' keys...
I think that if you reverse your if clauses you might get something that behaves more like what you are expecting, although it is somewhat unclear what you are asking. Comparing keys as the first clause in the if block makes the code simpler.
if( entry.getKey().trim().equals("nickname") )
{
System.out.print("Yes are sames");
}
else
{
System.out.print("'"+ entry.getKey() +"' contains "+ entry.getKey().length() +" chars");
System.out.print("'"+ name +"' contains "+ name.length() +" chars");
}

program to determine number of duplicates in a sentence

Code:public class duplicate
{
public static void main(String[] args)throws IOException
{
System.out.println("Enter words separated by spaces ('.' to quit):");
Set<String> s = new HashSet<String>();
Scanner input = new Scanner(System.in);
while (true)
{
String token = input.next();
if (".".equals(token))
break;
if (!s.add(token))
System.out.println("Duplicate detected: " + token);
}
System.out.println(s.size() + " distinct words:\n" + s);
Set<String> duplicatesnum = new HashSet<String>();
String token = input.next();
if (!s.add(token))
{
duplicatesnum.add(token);
System.out.println("Duplicate detected: " + token);
}
System.out.println(duplicatesnum.size());
}
}
the output is:
Enter words separated by spaces ('.' to quit):
one two one two .
Duplicate detected: one
Duplicate detected: two
2 distinct words:
[two, one]
I assume you want to know the number of different duplicate words. You can use another HashSet<String> for the duplicates.
//Outside the loop
Set<String> duplicates = new HashSet<String>();
//Inside the loop
if (!s.add(token))
{
duplicates.add(token);
System.out.println("Duplicate detected: " + token);
}
//Outside the loop
System.out.println(duplicates.size());
Also if you care for the occurences of each word declare a HashMap<String, Integer> as in others posts is mentioned.
But if you want the number of all duplicate words(not different) just declare a counter:
//Outside the loop
int duplicates = 0;
//Inside the loop
if (!s.add(token))
{
duplicates++;
System.out.println("Duplicate detected: " + token);
}
//Outside the loop
System.out.println(duplicates);
Instead of a HashSet, use a HashMap. A HashSet only stores the values. A HashMap maps a value to another value (see http://www.geekinterview.com/question_details/47545 for an explanation)
In your case, the key of the HashMap is your string (just as the key of the HashSet is the string). The value in the HashMap is the number of times you encountered this string.
When you find a new string, add it to the HashMap, and set the value of the entry to zero.
When you encounter the same string later, increment the value in the HashMap.
Because you are using a HashSet, you will not know how many duplicates you have. If you went with a HashMap<String, Integer>, you could increment whenever you found that your key was != null.
In the if (!s.add(token)), you can increment a counter and then display it's value at the end.
Your question is a bit misleading. Some people understand that you want:
Input: hello man, hello woman, say good by to your man.
Output:
Found duplicate: Hello
Found duplicate: Man
Duplicate count: 2
Others understood you wanted:
Input: hello man, hello woman, say hello to your man.
Output:
Found duplicate: Hello - 3 appearances
Found duplicate: Man - 2 appearances
Assuming you want the 1st option - go with Petar Minchev's solution
Assuming you want the 2nd option - go with Patrick's solution. Don't forget that when you use an Integer in a Map, you can get/put int as well, and Java will Automatically Box/Unbox it for you, but if you rely on this - you can get NPEs when asking the map for a key that does not exist:
Map<String,Integer> myMap = new HashMap<String,Integer>();
myMap.get("key that does not exist"); // NPE here <---
The NPE is caused since the return value from 'get' is null, and that value is being cast into an Integer after which the intValue() method will be invoked - thus triggering an NPE.
You can use Google collections library:
Multiset<String> words = HashMultiset.create();
while (true) {
String token = input.next();
if (".".equals(token))
break;
if (!words.add(token))
System.out.println("Duplicate detected: " + token);
}
System.out.println(words.elementSet().size() + " distinct words:\n" + words.elementSet());
Collection<Entry<String>> duplicateWords = Collections2.filter(words.entrySet(), new Predicate<Entry<String>>() {
public boolean apply(Entry<String> entry) {
return entry.getCount() > 1;
}
});
System.out.println("There are " + duplicateWords.size() + " duplicate words.");
System.out.println("The duplicate words are: " + Joiner.on(", ").join(duplicateWords));
Example of output:
Enter words separated by spaces ('.' to quit):
aaa bbb aaa ccc aaa bbb .
3 distinct words:
[aaa, ccc, bbb]
There are 2 duplicate words.
The duplicate words are: aaa x 3, bbb x 2

Categories