Unsure how this piece of code is doing what it does… .getDescribe() - java

I'm relatively new to Apex and Java.
Could someone possibly explain this snippet of code?
Map<String, SObjectField> m = Opportunity.SObjectType.getDescribe().fields.getMap();
for (String name : m.keySet()) {
DescribeFieldResult r = m.get(name).getDescribe();
System.debug(r);
}
I know it's getting the Describe information for each field on the Opportunity object, but could someone explain, line by line, how it's doing it?
Cheers!

This is about as basic as it gets when you need to enumerate a map:
Line 1 gets the map, and stores it in variable m
Line 2 iterates over the keys of the map m, using name variable for the value of the key in this iteration
Line 3 gets the item from the map m using name for the key, and calls getDescribe
Line 4 passes the result to System.debug
Line 5 closes the loop
However, this is not the best way of iterating the values, though: a simpler approach would be as follows:
Map<String, SObjectField> m = Opportunity.SObjectType.getDescribe().fields.getMap();
for (SObjectField val : m.values()) {
System.debug(val.getDescribe());
}
For completeness, if you would like to iterate both keys and values, iterate entrySet, like this:
Map<String, SObjectField> m = Opportunity.SObjectType.getDescribe().fields.getMap();
for (Map.Entry<String,SObjectField> e : m.entrySet()) {
// e.getKey() produces the key
// e.getValue() produces its associated value
}
Iterating keys and then retrieving the values in a separate call to get is inefficient.

Related

Retrieve String from values in HashMap at a specific occurrence of special character

So I'm trying retrieve specific substrings in values in a Hashmap constructed like this..
HashMap<ID, "Home > Recipe > Main Dish > Chicken > Chicken Breasts">
Which is passed from a different method that returns a HashMap
In above example, I need to retrieve Chicken.
Thus far, I have..
public static ArrayList<String> generalize() {
HashMap<String, String> items = new HashMap<>();
ArrayList<String> cats = new ArrayList<>();
items = RecSys.readInItemProfile("PATH", 0, 1);
for(String w : items.values()) {
cats.add(w);
}
for(String w : cats) {
int e = w.indexOf('>', 1 + w.indexOf('>', 1 + w.indexOf('>')));
String k = w.substring(e+1);
System.out.print(k);
e = 0;
}
System.out.println("k" + cats);
return cats;
}
Where I try to nullify String e for each iteration (I know it's redundant but it was just to test).
In my dataset, the first k-v pair is
3880=Home  >  Recipes  >  Main Dish  >  Pasta,
My output is
Pasta
Which is ok. If there are more than 3x ">", it'll return all following categories. Optimally it wouldn't do that, but it's ok if it does. However, further down the line, it (seemingly) randomly returns
Home > Recipe
Along with the rest of the data...
This happens at the 6th loop, I believe.
Any help is greatly appreciated..
Edit:
To clarify, I have a .csv file containing 3 columns, whereas 2 are used in this function (ID and Category). These are passed to this function by a read method in another class.
What I need to do is extract a generalized description of each category, which in all cases is the third instance of category specification (that is, always between the third and fourth ">" in every k-v pair).
My idea was to simply put all values in an arraylist, and for every value extract a string from between the third and fourth ">".
I recommend using the following map:
Map<Integer, List> map = new HashMap<>();
String[] vals = new String[] { "HomeRecipe", "Main Dish", "Chicken",
"Chicken Breasts" };
map.put(1, Arrays.asList(vals));
Then, if you need to find a given value in your original string using an ID, you can simply call ArrayList#get() at a certain position. If you don't care at all about order, then a map of integers to sets might make more sense here.
If you can. change your data structure to a HashMap<Integer, List<String>> or HashMap<Integer, String[]>. It's better to store the categories (by cats you mean categories right?) in a collection instead of a string.
Then you can easily get the third item.
If this is not possible. You need to do some debugging. Start by printing every input and output pair and find out which input caused the unexpected output. Your indexOf method seems to work at first glance.
Alternatively, try this regex method:
String k = cats.replaceAll("(?:[^>]+\\s*>\\s*){3}([^>]+).*", "$1");
System.out.println(k);
The regex basically looks for a xxx > yyy > zzz > aaa ... pattern and replaces that pattern with aaa (whatever that is in the original string).

Not entirely clear on what this code does? (Includes Set, HashMap and .keySet())

So I've finished a program and have had help building it/worked with another person. I understand all of the program in terms of what each line of code does except one part. This is the code:
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
Map<String, Integer> stringIntegerMap1 = set1.stream().collect(HashMap::new,
(hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
Some background info:
getWordCut is a method that looks like this:
public HashMap getWordCountsMap() {
HashMap<String, Integer> myHashMap = new HashMap<String, Integer>();
for (String word : this.getWordArray()) {
if (myHashMap.keySet().contains(word)) {
myHashMap.put(word, myHashMap.get(word) + 1);
} else {
myHashMap.put(word, 1);
}
}
return myHashMap;
}
firstWordGroup is a constructor that stores a string of words.
If anybody could explain exactly what this block of code does and how it does it then that would be helpful, thanks.
P.S: I'm not sure if supplying the whole program to reproduce the code is relevant so if you think it is, just leave a comment saying so and I will edit the question so you can reproduce the program.
getWordsCountsMap() returns a map where the key is a word and the value is how many times the word occurred in the array
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
The .keyset() method returns just the keys of the map, so now you have a set of the words, but have lost the occurrence counts.
Map<String, Integer> stringIntegerMap1 =
set1.stream()
.collect(HashMap::new,
(hashMap, s) -> hashMap.put(s, s.length()),
HashMap::putAll)
This is using Java8 streams to iterate through the set (words) originally put into a map and create a new hash map, where the key is the word (as it was before) and the value is the length of the word (whereas originally it was the word count). A new hash map is created and populated and returned.
What I'm not understanding is the final HashMap::putAll() which would seem to take the hashmap just populated and re-add all entries (which really would be a no-op because the keys would be replaced). Since I haven't whipped open my IDE to put in the code and test it (which, if you haven't yourself, would recommend, I'm just not interested enough to do so because it's not my problem!).
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
In essence, this is a cleaner way to iterate through the entries in the map created, printing out the word and length for each.
After working through this and thinking about it, I have a feeling I'm doing your homework for you, the real way to figure this out is to break things down and debug through your IDE and seeing what each step of the way does.
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
This line calles getWordCountsMap which returns a map from words to their count. It then ignores the count and just takes the words in a set. Note this could be achieved in a lot of much simpler ways.
Map<String, Integer> stringIntegerMap1 = set1.stream()
.collect(HashMap::new, (hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);
This converts the set of words to a stream and then collects the stream. The collector starts by creating a hash map then, for each word, adding a map from the to its length. If multiple maps are created (as is allowed in streams) then they are combined using putAll. Again there are much simpler and clearer ways to achieve this.
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
This line iterates through all entries in the map and prints out the key and value.
All this code could have been achieved with:
Arrays.stream(getWordArray())
.distinct().map(w -> w + ":" + w.length()).forEach(System.out::println);
This command converts the words to a stream, removes duplicates, maps the words to the output string then prints them.

Java writing map key to file for the number of times it is found in the input file (stored as the value of the map)

I have a text file that contains thousands of lines of 1 word/character. I have created a TreeMap<String, Integer> s = new TreeMap<>(); that stores each line from the text file as the key, and the value of the map is an integer that counts how many times the same word was found in the file (Duplicates).
I want to now write the results to the output file w, where the duplicates are printed as many times as they appear (counted as the map value).
As of now, I have the following code to write to the output file:
for (String value : s.keySet()) {
w.println(value);
}
This however only writes each key once in the output file. Essentially what I am trying to get is:
map:
[(hello, 1); (apple, 3); (java, 2); (python, 1)]
The output file should be:
apple
apple
apple
hello
java
java
python
You should loop over the entries of the map, not just the keys. The entry captures the key (which hold the word to write) and the value (which hold the number of times it should be written).
To get a hold of the entries, you call Map.entrySet(). This returns a Set<Map.Entry<String, Integer>> in your case. Map.Entry represents an entry of the map. Then:
getKey() returns the key of this entry, which is the word to write.
getValue() returns the value of this entry, which is the number of times it should be written.
Sample code:
for (Map.Entry<String, Integer> entry : s.entrySet()) {
for (int i = 0; i < entry.getValue(); i++) {
w.println(entry.getKey());
}
}
Your approach to use the keySet() method to retrieve the words is correct. Remember, you also have a corresponding value for each key which indicates how many times each word has been repeated.Make sure you use the value for each key so that you can print each word/character "value" number of times.

Iterating over the map and calling another method

I am getting an map as shown below inside a method
Map<Integer, Integer> result1 =jmxService.generateMabc(p1, p2,p3,p4);
now the map result 1 will consists oif key value pair as usal
now i want to iterate over the map one by one , fetch the value of the map
that is both key and value which will be of type integer and convert them into string
and store the string two string variables like shown below
string j = will store the key
string t = will store the value
amd then pass these two parameters to another method call which wil take string
j and string t as parameter once they pass i want j and t to be null so that in next iteration the same process and can be continued till the time map has value c an you please advise how to achieve this, what I have tried is..
for (Map.Entry<Integer, Integer> entry : result1.entrySet())
{
String j, t;
j=entry.getKey();
t= entry.getValue();
abc .callanothermethod(string p1,stringp2, stringj, string t)
j=null;
t=null;
}
please advise what will be the correct appoach to obtain the same.
An Integer is not a String. So j = entry.getKey() doesn't make sense.
You need to transform the Integer into a String (by calling toString() for example):
j = entry.getKey().toString();
You really need to learn to
read the error messages from the compiler, which tell you waht is wrong and where
read the javadoc of the classes you're using, to understand what you can do with them.

How to split next entryset iterator?

Hello I'm trying to split next iterator entryset from hashmap but I can't get it to work.
I have an hashmap in which I put two things, first one is sender, second one is channel:
channelList = HashMap()
channelList.put(playername, channelname) #have on mind that those can be changed, depending on what user types in
I have this iterator:
it = channelList.entrySet().iterator()
next = it.next()
But when I print next out it has "=" between arguments from hashmap. For example, if playername is PLAYER and channel name is balkan I get as result: PLAYER=balkan. Question is, how do I get ONLY PLAYERNAME on every next. I tried splitting it like this, but it's not working:
next = it.next()
realnext = next.split("=")
realrealnext = realnext.split("=")[0]
Have on mind that I check for every next using this while loop:
while it.hasNext():
Thanks in advance, Amar!
P.S. I'm jython/python programmer.
The problem is you're casting java.util.Map.Entry to a String. Try this instead
#!/usr/bin/jython
import java.util.HashMap
channelList = java.util.HashMap()
channelList.put("Hello", "World")
it = channelList.entrySet().iterator()
while (it.hasNext()):
e = it.next()
print("key = " + e.getKey())
print("value = " + e.getValue())
Which on my system runs as follows -
$ ./test.py
key = Hello
value = World
$
You shouldn't name reference to Map ....List, it is confusing. You should name it channelMap.
Next, your Maps should use generic types to set up elements they are using, like for example
Map<String, Channel> channelMap = new HashMap<>();
This way you would be able to safely use
Iterator<Entry<String, Channel>> it = channelMap.entrySet().iterator();
and have access to it.next().getKey() (notice that order of elements in HashMap is based on hashCode if its Key so don't be surprised with order like Player2, Player1, Player 3).
Anyway if you just want to iterate over all keys then maybe
for (String key: channelMap.keySet()){
System.out.println(key);
}
would be better solution.

Categories