Generating a string in a particular format by reading data from a map











up vote
2
down vote

favorite












I have a processToTaskIdHolder Map which contains processId as the key and taskId as the value. Now I am iterating this map and at the end I am making a String in particular format.



For example:-




  • Let's say I have 123 as the key and 009 is the value in the processToTaskIdHolder map.

  • Now I will make a "activityKey" using 123 and then get data basis on this key.

  • Now I will iterate all the categories for that activityKey and check whether those categoryId are already present in processToTaskIdHolder keyset or not. If they are present, then I will extract taskId for that categoryId from the map and also extract score for that categoryId and store it in an Info class.

  • Same category can be present with different score for different processId.


Now I need to repeat above steps for each activity I have in activities list.



So my formatted string will be like this:-



A,B,C:Score1,D:Score2
P,Q,R:Score1,S:Score2



  • Where A is the categoryId for the processId C and D, and Score1 is the score for categoryId A for processId C. Score2 is the score for categoryId A but for processId D. We have different scores for same categories for two different processes. It means, categoryId A was present in both processId C and D so I need to get the score for both the cases and make a string like that. And B is the taskId for categoryId A which will be present in the map.

  • Where P is the categoryId for the processId R and S, and Score1 is the score for categoryId P for processId R. Score2 is the score for categoryId P but for processId S. We have different scores for same categories for two different processes. It means, categoryId P was present in both processId R and S so I need to get the score for both the cases and make a string like that. And Q is the taskId for categoryId P which will be present in the map.


I have this code which does the job but I think it's not the right and efficient way to achieve above formatted string. I believe it can be done in a much better way.



  private static final List<String> activities = Arrays.asList("tree", "gold", "print", "catch");

public static void reverseLookup(final String clientId, final Map<String, String> processToTaskIdHolder) {
Multimap<String, Info> reverseLookup = LinkedListMultimap.create();
for (String activity : activities) {
for (Entry<String, String> entry : processToTaskIdHolder.entrySet()) {
String activityKey = "abc_" + activity + "_" + clientId + "_" + entry.getKey();
Optional<Datum> datum = getData(activityKey);
if (!datum.isPresent()) {
continue;
}
List<Categories> categories = datum.get().getCategories();
for (Categories category : categories) {
String categoryId = String.valueOf(category.getLeafCategId());
if (processToTaskIdHolder.containsKey(categoryId)) {
Info info = new Info(entry.getKey(), String.valueOf(category.getScore()));
reverseLookup.put(categoryId + ":" + processToTaskIdHolder.get(categoryId), info);
}
}
}
String formattedString = generateString(reverseLookup);
System.out.println(formattedString);
}
}

private static String generateString(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();
for (Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
sb.append(entry.getKey().split(":")[0]).append(",").append(entry.getKey().split(":")[1])
.append(",");
String sep = "";
for (Info info : entry.getValue()) {
sb.append(sep).append(info.getLeafCategoryId()).append(":").append(info.getScore());
sep = ",";
}
sb.append(System.getProperty("line.separator"));
}
return sb.toString();
}


In the reverseLookup map, I have a key in this format - "a:b", so I'm not sure instead of making a key like that. Maybe it can be done in some other better way?



Note: I am working with Java 7. Categories and Info class is a simple immutable class with basic toString implementations.










share|improve this question
















bumped to the homepage by Community yesterday


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.















  • "Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
    – Stephen C
    Jan 28 at 1:41












  • Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
    – user1950349
    Jan 28 at 1:42










  • Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
    – Sergii Nevydanchuk
    Feb 6 at 3:49










  • What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
    – user1950349
    Feb 6 at 4:00















up vote
2
down vote

favorite












I have a processToTaskIdHolder Map which contains processId as the key and taskId as the value. Now I am iterating this map and at the end I am making a String in particular format.



For example:-




  • Let's say I have 123 as the key and 009 is the value in the processToTaskIdHolder map.

  • Now I will make a "activityKey" using 123 and then get data basis on this key.

  • Now I will iterate all the categories for that activityKey and check whether those categoryId are already present in processToTaskIdHolder keyset or not. If they are present, then I will extract taskId for that categoryId from the map and also extract score for that categoryId and store it in an Info class.

  • Same category can be present with different score for different processId.


Now I need to repeat above steps for each activity I have in activities list.



So my formatted string will be like this:-



A,B,C:Score1,D:Score2
P,Q,R:Score1,S:Score2



  • Where A is the categoryId for the processId C and D, and Score1 is the score for categoryId A for processId C. Score2 is the score for categoryId A but for processId D. We have different scores for same categories for two different processes. It means, categoryId A was present in both processId C and D so I need to get the score for both the cases and make a string like that. And B is the taskId for categoryId A which will be present in the map.

  • Where P is the categoryId for the processId R and S, and Score1 is the score for categoryId P for processId R. Score2 is the score for categoryId P but for processId S. We have different scores for same categories for two different processes. It means, categoryId P was present in both processId R and S so I need to get the score for both the cases and make a string like that. And Q is the taskId for categoryId P which will be present in the map.


I have this code which does the job but I think it's not the right and efficient way to achieve above formatted string. I believe it can be done in a much better way.



  private static final List<String> activities = Arrays.asList("tree", "gold", "print", "catch");

public static void reverseLookup(final String clientId, final Map<String, String> processToTaskIdHolder) {
Multimap<String, Info> reverseLookup = LinkedListMultimap.create();
for (String activity : activities) {
for (Entry<String, String> entry : processToTaskIdHolder.entrySet()) {
String activityKey = "abc_" + activity + "_" + clientId + "_" + entry.getKey();
Optional<Datum> datum = getData(activityKey);
if (!datum.isPresent()) {
continue;
}
List<Categories> categories = datum.get().getCategories();
for (Categories category : categories) {
String categoryId = String.valueOf(category.getLeafCategId());
if (processToTaskIdHolder.containsKey(categoryId)) {
Info info = new Info(entry.getKey(), String.valueOf(category.getScore()));
reverseLookup.put(categoryId + ":" + processToTaskIdHolder.get(categoryId), info);
}
}
}
String formattedString = generateString(reverseLookup);
System.out.println(formattedString);
}
}

private static String generateString(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();
for (Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
sb.append(entry.getKey().split(":")[0]).append(",").append(entry.getKey().split(":")[1])
.append(",");
String sep = "";
for (Info info : entry.getValue()) {
sb.append(sep).append(info.getLeafCategoryId()).append(":").append(info.getScore());
sep = ",";
}
sb.append(System.getProperty("line.separator"));
}
return sb.toString();
}


In the reverseLookup map, I have a key in this format - "a:b", so I'm not sure instead of making a key like that. Maybe it can be done in some other better way?



Note: I am working with Java 7. Categories and Info class is a simple immutable class with basic toString implementations.










share|improve this question
















bumped to the homepage by Community yesterday


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.















  • "Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
    – Stephen C
    Jan 28 at 1:41












  • Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
    – user1950349
    Jan 28 at 1:42










  • Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
    – Sergii Nevydanchuk
    Feb 6 at 3:49










  • What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
    – user1950349
    Feb 6 at 4:00













up vote
2
down vote

favorite









up vote
2
down vote

favorite











I have a processToTaskIdHolder Map which contains processId as the key and taskId as the value. Now I am iterating this map and at the end I am making a String in particular format.



For example:-




  • Let's say I have 123 as the key and 009 is the value in the processToTaskIdHolder map.

  • Now I will make a "activityKey" using 123 and then get data basis on this key.

  • Now I will iterate all the categories for that activityKey and check whether those categoryId are already present in processToTaskIdHolder keyset or not. If they are present, then I will extract taskId for that categoryId from the map and also extract score for that categoryId and store it in an Info class.

  • Same category can be present with different score for different processId.


Now I need to repeat above steps for each activity I have in activities list.



So my formatted string will be like this:-



A,B,C:Score1,D:Score2
P,Q,R:Score1,S:Score2



  • Where A is the categoryId for the processId C and D, and Score1 is the score for categoryId A for processId C. Score2 is the score for categoryId A but for processId D. We have different scores for same categories for two different processes. It means, categoryId A was present in both processId C and D so I need to get the score for both the cases and make a string like that. And B is the taskId for categoryId A which will be present in the map.

  • Where P is the categoryId for the processId R and S, and Score1 is the score for categoryId P for processId R. Score2 is the score for categoryId P but for processId S. We have different scores for same categories for two different processes. It means, categoryId P was present in both processId R and S so I need to get the score for both the cases and make a string like that. And Q is the taskId for categoryId P which will be present in the map.


I have this code which does the job but I think it's not the right and efficient way to achieve above formatted string. I believe it can be done in a much better way.



  private static final List<String> activities = Arrays.asList("tree", "gold", "print", "catch");

public static void reverseLookup(final String clientId, final Map<String, String> processToTaskIdHolder) {
Multimap<String, Info> reverseLookup = LinkedListMultimap.create();
for (String activity : activities) {
for (Entry<String, String> entry : processToTaskIdHolder.entrySet()) {
String activityKey = "abc_" + activity + "_" + clientId + "_" + entry.getKey();
Optional<Datum> datum = getData(activityKey);
if (!datum.isPresent()) {
continue;
}
List<Categories> categories = datum.get().getCategories();
for (Categories category : categories) {
String categoryId = String.valueOf(category.getLeafCategId());
if (processToTaskIdHolder.containsKey(categoryId)) {
Info info = new Info(entry.getKey(), String.valueOf(category.getScore()));
reverseLookup.put(categoryId + ":" + processToTaskIdHolder.get(categoryId), info);
}
}
}
String formattedString = generateString(reverseLookup);
System.out.println(formattedString);
}
}

private static String generateString(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();
for (Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
sb.append(entry.getKey().split(":")[0]).append(",").append(entry.getKey().split(":")[1])
.append(",");
String sep = "";
for (Info info : entry.getValue()) {
sb.append(sep).append(info.getLeafCategoryId()).append(":").append(info.getScore());
sep = ",";
}
sb.append(System.getProperty("line.separator"));
}
return sb.toString();
}


In the reverseLookup map, I have a key in this format - "a:b", so I'm not sure instead of making a key like that. Maybe it can be done in some other better way?



Note: I am working with Java 7. Categories and Info class is a simple immutable class with basic toString implementations.










share|improve this question















I have a processToTaskIdHolder Map which contains processId as the key and taskId as the value. Now I am iterating this map and at the end I am making a String in particular format.



For example:-




  • Let's say I have 123 as the key and 009 is the value in the processToTaskIdHolder map.

  • Now I will make a "activityKey" using 123 and then get data basis on this key.

  • Now I will iterate all the categories for that activityKey and check whether those categoryId are already present in processToTaskIdHolder keyset or not. If they are present, then I will extract taskId for that categoryId from the map and also extract score for that categoryId and store it in an Info class.

  • Same category can be present with different score for different processId.


Now I need to repeat above steps for each activity I have in activities list.



So my formatted string will be like this:-



A,B,C:Score1,D:Score2
P,Q,R:Score1,S:Score2



  • Where A is the categoryId for the processId C and D, and Score1 is the score for categoryId A for processId C. Score2 is the score for categoryId A but for processId D. We have different scores for same categories for two different processes. It means, categoryId A was present in both processId C and D so I need to get the score for both the cases and make a string like that. And B is the taskId for categoryId A which will be present in the map.

  • Where P is the categoryId for the processId R and S, and Score1 is the score for categoryId P for processId R. Score2 is the score for categoryId P but for processId S. We have different scores for same categories for two different processes. It means, categoryId P was present in both processId R and S so I need to get the score for both the cases and make a string like that. And Q is the taskId for categoryId P which will be present in the map.


I have this code which does the job but I think it's not the right and efficient way to achieve above formatted string. I believe it can be done in a much better way.



  private static final List<String> activities = Arrays.asList("tree", "gold", "print", "catch");

public static void reverseLookup(final String clientId, final Map<String, String> processToTaskIdHolder) {
Multimap<String, Info> reverseLookup = LinkedListMultimap.create();
for (String activity : activities) {
for (Entry<String, String> entry : processToTaskIdHolder.entrySet()) {
String activityKey = "abc_" + activity + "_" + clientId + "_" + entry.getKey();
Optional<Datum> datum = getData(activityKey);
if (!datum.isPresent()) {
continue;
}
List<Categories> categories = datum.get().getCategories();
for (Categories category : categories) {
String categoryId = String.valueOf(category.getLeafCategId());
if (processToTaskIdHolder.containsKey(categoryId)) {
Info info = new Info(entry.getKey(), String.valueOf(category.getScore()));
reverseLookup.put(categoryId + ":" + processToTaskIdHolder.get(categoryId), info);
}
}
}
String formattedString = generateString(reverseLookup);
System.out.println(formattedString);
}
}

private static String generateString(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();
for (Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
sb.append(entry.getKey().split(":")[0]).append(",").append(entry.getKey().split(":")[1])
.append(",");
String sep = "";
for (Info info : entry.getValue()) {
sb.append(sep).append(info.getLeafCategoryId()).append(":").append(info.getScore());
sep = ",";
}
sb.append(System.getProperty("line.separator"));
}
return sb.toString();
}


In the reverseLookup map, I have a key in this format - "a:b", so I'm not sure instead of making a key like that. Maybe it can be done in some other better way?



Note: I am working with Java 7. Categories and Info class is a simple immutable class with basic toString implementations.







java performance algorithm guava






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 29 at 17:29

























asked Jan 28 at 0:00









user1950349

1661518




1661518





bumped to the homepage by Community yesterday


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community yesterday


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.














  • "Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
    – Stephen C
    Jan 28 at 1:41












  • Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
    – user1950349
    Jan 28 at 1:42










  • Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
    – Sergii Nevydanchuk
    Feb 6 at 3:49










  • What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
    – user1950349
    Feb 6 at 4:00


















  • "Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
    – Stephen C
    Jan 28 at 1:41












  • Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
    – user1950349
    Jan 28 at 1:42










  • Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
    – Sergii Nevydanchuk
    Feb 6 at 3:49










  • What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
    – user1950349
    Feb 6 at 4:00
















"Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
– Stephen C
Jan 28 at 1:41






"Note: I am working with Java 7." - Java 7 has been end-of-lifed by Oracle. It is time you / your organization made the move. The longer you leave it, the harder it will get.
– Stephen C
Jan 28 at 1:41














Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
– user1950349
Jan 28 at 1:42




Yeah until my organization makes a move, I am stuck with Java7 but I am sure we will start using Java8 very soon.
– user1950349
Jan 28 at 1:42












Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
– Sergii Nevydanchuk
Feb 6 at 3:49




Could you drop the snippet you provided here in an absolutely new project on your machine and see what it says missing? Maybe a simplified version of each class mentioned in your code, so it works in IDE. Meanwhile, I'll rethink the logic you've described here.
– Sergii Nevydanchuk
Feb 6 at 3:49












What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
– user1950349
Feb 6 at 4:00




What I have not provided is - Info and Categories classes. You can assume that they are immutable classes.
– user1950349
Feb 6 at 4:00










2 Answers
2






active

oldest

votes

















up vote
0
down vote













This looks horrible heavy for me with this "formates"

- instead of creating info i d just create a string what will be printed like: String info = entry.getKey() +categoryId + String.valueOf(category.getScore());
- Then having Multimap map just:



 map.asMap().entrySet().stream().forEach( e->System.out.println(e));


Or this in 1.7 like:

Like:



public static<M,N> String entryLnInvert(Map<M,N> map, String keyFormat, String between, String valueFormat) {

StringBuilder sb = new StringBuilder();
for( Entry<M,N> e: map.entrySet()) {
sb.append(String.format(valueFormat,e.getValue()));
sb.append(between);
sb.append(String.format(keyFormat,e.getKey()));
}
return sb.toString();
}


and other crap you just put in toString() of N,M classes

such printout would be enoph for me






share|improve this answer























  • I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
    – user1950349
    Jan 28 at 0:27










  • This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
    – user1950349
    Jan 28 at 0:39












  • both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
    – user8426627
    Jan 28 at 0:50












  • yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
    – user1950349
    Jan 28 at 0:51










  • i dont understad your code fully, also where the Collection<String> activities comes from.
    – user8426627
    Jan 28 at 0:53




















up vote
0
down vote













Ok, first of all. If you don't understand things right away, usually it means code is messy. Code gets messy when you don't have time to think and you just need to do it. I've refactored junior/mids code and even seniors code produced when people just want to do it right away and don't have time to think.
So for the future. The way you approach is this is start simplifying, make the method do one thing. Get rid of repetitive parts.
So with first iteration I refactored to this



public class CategoryHolder {

// when in your code you have System.getProperty() called many times - do you need that?
// Its not changing every second, so when you store in variable, you're good then
private static final String END_OF_LINE = System.getProperty("line.separator");
// you used "," many times - its called magic string or if some number
// is jumping here and there in code its called magic number
// when you define the variable then you change in ONE place when something changes
private static final String COMMA = ",";
// same here, name is stupid maybe, but it's better than ":" all around your code
// rename it to something more meaningful
private static final String DOUBLE_DOT = ":";
private static final String EMPTY_STRING = "";

// I don't like the name of the method, but ok, its a first iteration of refactoring
private static String generateString(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();

for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
String splitThing = entry.getKey().split(DOUBLE_DOT);
// I started to simplify and immediately seen you do split two times
// while it could be done only once.. good catch
// you might use some meaningful names, I just don't know much about your domain
String something1 = splitThing[0]; // your doing split two times?
// same here
String something2 = splitThing[1];
sb.append(something1).append(COMMA).append(something2).append(COMMA);

createInfoString(sb, entry);

sb.append(END_OF_LINE);
}
return sb.toString();
}

private static void createInfoString(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
// I guess you've made it as the case to "" for first but "," for all next
// I would probably go with for(int i=0; i<entry.length? ; i++){
// separator = i == 0 ? EMPTY_STRING : DOUBLE_DOT;
String separator = EMPTY_STRING;
for (Info info : entry.getValue()) {
sb.append(separator)
sb.append(info.getLeafCategoryId())
sb.append(DOUBLE_DOT).append(info.getScore());
separator = COMMA;
}
}


It's a first step, but looks a bit more clear for me.



Now we do a bit more refactoring and its starts to get more clear what we do here



public class DataFormatter {

private static final String END_OF_LINE = System.getProperty("line.separator");
private static final String COMMA = ",";
private static final String DOUBLE_DOT = ":";
private static final String EMPTY_STRING = "";
private static final int NICE_PART_1_INDEX = 0;
private static final int NICE_PART_2_INDEX = 1;

private static String format(final Multimap<String, Info> reverseLookup) {
StringBuilder sb = new StringBuilder();

for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
formatKey(sb, entry.getKey());
formatValue(sb, entry);
sb.append(END_OF_LINE);
}

return sb.toString();
}

private static void formatKey(StringBuilder sb, String key) {
String splitThing = key.split(DOUBLE_DOT);
String something1 = splitThing[NICE_PART_1_INDEX];
String something2 = splitThing[NICE_PART_2_INDEX];

sb.append(something1).append(COMMA).append(something2).append(COMMA);
}

private static void formatValue(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
String separator = EMPTY_STRING;

for (Info info : entry.getValue()) {
sb.append(separator);
sb.append(info.getLeafCategoryId()).append(DOUBLE_DOT).append(info.getScore());
separator = COMMA;
}
}


At the end, I added formatting code to class and called DataFormatter and format() method. If you would have formatting in 5 different places you could move them to this class, see common parts, reuse them rather than copy/paste similar code in many places.



I would say - add unit tests which would pass any bad thing into your method you could imagine. Then you will be sure that your code works fine.






share|improve this answer























    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186168%2fgenerating-a-string-in-a-particular-format-by-reading-data-from-a-map%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    This looks horrible heavy for me with this "formates"

    - instead of creating info i d just create a string what will be printed like: String info = entry.getKey() +categoryId + String.valueOf(category.getScore());
    - Then having Multimap map just:



     map.asMap().entrySet().stream().forEach( e->System.out.println(e));


    Or this in 1.7 like:

    Like:



    public static<M,N> String entryLnInvert(Map<M,N> map, String keyFormat, String between, String valueFormat) {

    StringBuilder sb = new StringBuilder();
    for( Entry<M,N> e: map.entrySet()) {
    sb.append(String.format(valueFormat,e.getValue()));
    sb.append(between);
    sb.append(String.format(keyFormat,e.getKey()));
    }
    return sb.toString();
    }


    and other crap you just put in toString() of N,M classes

    such printout would be enoph for me






    share|improve this answer























    • I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
      – user1950349
      Jan 28 at 0:27










    • This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
      – user1950349
      Jan 28 at 0:39












    • both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
      – user8426627
      Jan 28 at 0:50












    • yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
      – user1950349
      Jan 28 at 0:51










    • i dont understad your code fully, also where the Collection<String> activities comes from.
      – user8426627
      Jan 28 at 0:53

















    up vote
    0
    down vote













    This looks horrible heavy for me with this "formates"

    - instead of creating info i d just create a string what will be printed like: String info = entry.getKey() +categoryId + String.valueOf(category.getScore());
    - Then having Multimap map just:



     map.asMap().entrySet().stream().forEach( e->System.out.println(e));


    Or this in 1.7 like:

    Like:



    public static<M,N> String entryLnInvert(Map<M,N> map, String keyFormat, String between, String valueFormat) {

    StringBuilder sb = new StringBuilder();
    for( Entry<M,N> e: map.entrySet()) {
    sb.append(String.format(valueFormat,e.getValue()));
    sb.append(between);
    sb.append(String.format(keyFormat,e.getKey()));
    }
    return sb.toString();
    }


    and other crap you just put in toString() of N,M classes

    such printout would be enoph for me






    share|improve this answer























    • I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
      – user1950349
      Jan 28 at 0:27










    • This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
      – user1950349
      Jan 28 at 0:39












    • both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
      – user8426627
      Jan 28 at 0:50












    • yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
      – user1950349
      Jan 28 at 0:51










    • i dont understad your code fully, also where the Collection<String> activities comes from.
      – user8426627
      Jan 28 at 0:53















    up vote
    0
    down vote










    up vote
    0
    down vote









    This looks horrible heavy for me with this "formates"

    - instead of creating info i d just create a string what will be printed like: String info = entry.getKey() +categoryId + String.valueOf(category.getScore());
    - Then having Multimap map just:



     map.asMap().entrySet().stream().forEach( e->System.out.println(e));


    Or this in 1.7 like:

    Like:



    public static<M,N> String entryLnInvert(Map<M,N> map, String keyFormat, String between, String valueFormat) {

    StringBuilder sb = new StringBuilder();
    for( Entry<M,N> e: map.entrySet()) {
    sb.append(String.format(valueFormat,e.getValue()));
    sb.append(between);
    sb.append(String.format(keyFormat,e.getKey()));
    }
    return sb.toString();
    }


    and other crap you just put in toString() of N,M classes

    such printout would be enoph for me






    share|improve this answer














    This looks horrible heavy for me with this "formates"

    - instead of creating info i d just create a string what will be printed like: String info = entry.getKey() +categoryId + String.valueOf(category.getScore());
    - Then having Multimap map just:



     map.asMap().entrySet().stream().forEach( e->System.out.println(e));


    Or this in 1.7 like:

    Like:



    public static<M,N> String entryLnInvert(Map<M,N> map, String keyFormat, String between, String valueFormat) {

    StringBuilder sb = new StringBuilder();
    for( Entry<M,N> e: map.entrySet()) {
    sb.append(String.format(valueFormat,e.getValue()));
    sb.append(between);
    sb.append(String.format(keyFormat,e.getKey()));
    }
    return sb.toString();
    }


    and other crap you just put in toString() of N,M classes

    such printout would be enoph for me







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 28 at 0:38

























    answered Jan 28 at 0:21









    user8426627

    1343




    1343












    • I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
      – user1950349
      Jan 28 at 0:27










    • This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
      – user1950349
      Jan 28 at 0:39












    • both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
      – user8426627
      Jan 28 at 0:50












    • yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
      – user1950349
      Jan 28 at 0:51










    • i dont understad your code fully, also where the Collection<String> activities comes from.
      – user8426627
      Jan 28 at 0:53




















    • I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
      – user1950349
      Jan 28 at 0:27










    • This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
      – user1950349
      Jan 28 at 0:39












    • both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
      – user8426627
      Jan 28 at 0:50












    • yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
      – user1950349
      Jan 28 at 0:51










    • i dont understad your code fully, also where the Collection<String> activities comes from.
      – user8426627
      Jan 28 at 0:53


















    I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
    – user1950349
    Jan 28 at 0:27




    I am working with Java7 so can't use Java8 unfortunately. Yeah I know it might not be efficient way so that's why I was trying to see if there is any better way. Can you provide an example basis on my code in Java7 to make myself clear?
    – user1950349
    Jan 28 at 0:27












    This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
    – user1950349
    Jan 28 at 0:39






    This method will replace which of my method? Still confuse how does this method is being used and from where it is being called. Do you think you can provide an example with my code to make it more clear?
    – user1950349
    Jan 28 at 0:39














    both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
    – user8426627
    Jan 28 at 0:50






    both, dont convert a map to another map for printout. also java 7 easy becomes java8 if you define your own functor like: interface Formatter<N,String> {public String format(N value) and use it as additional parameter in entryLnInvert
    – user8426627
    Jan 28 at 0:50














    yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
    – user1950349
    Jan 28 at 0:51




    yeah agreed but I am not able to understand how to use your suggestion to do that. Do you think you can edit your suggestion basis on my code so that I can understand how it will work? As of now I am confuse on how this will work.
    – user1950349
    Jan 28 at 0:51












    i dont understad your code fully, also where the Collection<String> activities comes from.
    – user8426627
    Jan 28 at 0:53






    i dont understad your code fully, also where the Collection<String> activities comes from.
    – user8426627
    Jan 28 at 0:53














    up vote
    0
    down vote













    Ok, first of all. If you don't understand things right away, usually it means code is messy. Code gets messy when you don't have time to think and you just need to do it. I've refactored junior/mids code and even seniors code produced when people just want to do it right away and don't have time to think.
    So for the future. The way you approach is this is start simplifying, make the method do one thing. Get rid of repetitive parts.
    So with first iteration I refactored to this



    public class CategoryHolder {

    // when in your code you have System.getProperty() called many times - do you need that?
    // Its not changing every second, so when you store in variable, you're good then
    private static final String END_OF_LINE = System.getProperty("line.separator");
    // you used "," many times - its called magic string or if some number
    // is jumping here and there in code its called magic number
    // when you define the variable then you change in ONE place when something changes
    private static final String COMMA = ",";
    // same here, name is stupid maybe, but it's better than ":" all around your code
    // rename it to something more meaningful
    private static final String DOUBLE_DOT = ":";
    private static final String EMPTY_STRING = "";

    // I don't like the name of the method, but ok, its a first iteration of refactoring
    private static String generateString(final Multimap<String, Info> reverseLookup) {
    StringBuilder sb = new StringBuilder();

    for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
    String splitThing = entry.getKey().split(DOUBLE_DOT);
    // I started to simplify and immediately seen you do split two times
    // while it could be done only once.. good catch
    // you might use some meaningful names, I just don't know much about your domain
    String something1 = splitThing[0]; // your doing split two times?
    // same here
    String something2 = splitThing[1];
    sb.append(something1).append(COMMA).append(something2).append(COMMA);

    createInfoString(sb, entry);

    sb.append(END_OF_LINE);
    }
    return sb.toString();
    }

    private static void createInfoString(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
    // I guess you've made it as the case to "" for first but "," for all next
    // I would probably go with for(int i=0; i<entry.length? ; i++){
    // separator = i == 0 ? EMPTY_STRING : DOUBLE_DOT;
    String separator = EMPTY_STRING;
    for (Info info : entry.getValue()) {
    sb.append(separator)
    sb.append(info.getLeafCategoryId())
    sb.append(DOUBLE_DOT).append(info.getScore());
    separator = COMMA;
    }
    }


    It's a first step, but looks a bit more clear for me.



    Now we do a bit more refactoring and its starts to get more clear what we do here



    public class DataFormatter {

    private static final String END_OF_LINE = System.getProperty("line.separator");
    private static final String COMMA = ",";
    private static final String DOUBLE_DOT = ":";
    private static final String EMPTY_STRING = "";
    private static final int NICE_PART_1_INDEX = 0;
    private static final int NICE_PART_2_INDEX = 1;

    private static String format(final Multimap<String, Info> reverseLookup) {
    StringBuilder sb = new StringBuilder();

    for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
    formatKey(sb, entry.getKey());
    formatValue(sb, entry);
    sb.append(END_OF_LINE);
    }

    return sb.toString();
    }

    private static void formatKey(StringBuilder sb, String key) {
    String splitThing = key.split(DOUBLE_DOT);
    String something1 = splitThing[NICE_PART_1_INDEX];
    String something2 = splitThing[NICE_PART_2_INDEX];

    sb.append(something1).append(COMMA).append(something2).append(COMMA);
    }

    private static void formatValue(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
    String separator = EMPTY_STRING;

    for (Info info : entry.getValue()) {
    sb.append(separator);
    sb.append(info.getLeafCategoryId()).append(DOUBLE_DOT).append(info.getScore());
    separator = COMMA;
    }
    }


    At the end, I added formatting code to class and called DataFormatter and format() method. If you would have formatting in 5 different places you could move them to this class, see common parts, reuse them rather than copy/paste similar code in many places.



    I would say - add unit tests which would pass any bad thing into your method you could imagine. Then you will be sure that your code works fine.






    share|improve this answer



























      up vote
      0
      down vote













      Ok, first of all. If you don't understand things right away, usually it means code is messy. Code gets messy when you don't have time to think and you just need to do it. I've refactored junior/mids code and even seniors code produced when people just want to do it right away and don't have time to think.
      So for the future. The way you approach is this is start simplifying, make the method do one thing. Get rid of repetitive parts.
      So with first iteration I refactored to this



      public class CategoryHolder {

      // when in your code you have System.getProperty() called many times - do you need that?
      // Its not changing every second, so when you store in variable, you're good then
      private static final String END_OF_LINE = System.getProperty("line.separator");
      // you used "," many times - its called magic string or if some number
      // is jumping here and there in code its called magic number
      // when you define the variable then you change in ONE place when something changes
      private static final String COMMA = ",";
      // same here, name is stupid maybe, but it's better than ":" all around your code
      // rename it to something more meaningful
      private static final String DOUBLE_DOT = ":";
      private static final String EMPTY_STRING = "";

      // I don't like the name of the method, but ok, its a first iteration of refactoring
      private static String generateString(final Multimap<String, Info> reverseLookup) {
      StringBuilder sb = new StringBuilder();

      for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
      String splitThing = entry.getKey().split(DOUBLE_DOT);
      // I started to simplify and immediately seen you do split two times
      // while it could be done only once.. good catch
      // you might use some meaningful names, I just don't know much about your domain
      String something1 = splitThing[0]; // your doing split two times?
      // same here
      String something2 = splitThing[1];
      sb.append(something1).append(COMMA).append(something2).append(COMMA);

      createInfoString(sb, entry);

      sb.append(END_OF_LINE);
      }
      return sb.toString();
      }

      private static void createInfoString(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
      // I guess you've made it as the case to "" for first but "," for all next
      // I would probably go with for(int i=0; i<entry.length? ; i++){
      // separator = i == 0 ? EMPTY_STRING : DOUBLE_DOT;
      String separator = EMPTY_STRING;
      for (Info info : entry.getValue()) {
      sb.append(separator)
      sb.append(info.getLeafCategoryId())
      sb.append(DOUBLE_DOT).append(info.getScore());
      separator = COMMA;
      }
      }


      It's a first step, but looks a bit more clear for me.



      Now we do a bit more refactoring and its starts to get more clear what we do here



      public class DataFormatter {

      private static final String END_OF_LINE = System.getProperty("line.separator");
      private static final String COMMA = ",";
      private static final String DOUBLE_DOT = ":";
      private static final String EMPTY_STRING = "";
      private static final int NICE_PART_1_INDEX = 0;
      private static final int NICE_PART_2_INDEX = 1;

      private static String format(final Multimap<String, Info> reverseLookup) {
      StringBuilder sb = new StringBuilder();

      for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
      formatKey(sb, entry.getKey());
      formatValue(sb, entry);
      sb.append(END_OF_LINE);
      }

      return sb.toString();
      }

      private static void formatKey(StringBuilder sb, String key) {
      String splitThing = key.split(DOUBLE_DOT);
      String something1 = splitThing[NICE_PART_1_INDEX];
      String something2 = splitThing[NICE_PART_2_INDEX];

      sb.append(something1).append(COMMA).append(something2).append(COMMA);
      }

      private static void formatValue(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
      String separator = EMPTY_STRING;

      for (Info info : entry.getValue()) {
      sb.append(separator);
      sb.append(info.getLeafCategoryId()).append(DOUBLE_DOT).append(info.getScore());
      separator = COMMA;
      }
      }


      At the end, I added formatting code to class and called DataFormatter and format() method. If you would have formatting in 5 different places you could move them to this class, see common parts, reuse them rather than copy/paste similar code in many places.



      I would say - add unit tests which would pass any bad thing into your method you could imagine. Then you will be sure that your code works fine.






      share|improve this answer

























        up vote
        0
        down vote










        up vote
        0
        down vote









        Ok, first of all. If you don't understand things right away, usually it means code is messy. Code gets messy when you don't have time to think and you just need to do it. I've refactored junior/mids code and even seniors code produced when people just want to do it right away and don't have time to think.
        So for the future. The way you approach is this is start simplifying, make the method do one thing. Get rid of repetitive parts.
        So with first iteration I refactored to this



        public class CategoryHolder {

        // when in your code you have System.getProperty() called many times - do you need that?
        // Its not changing every second, so when you store in variable, you're good then
        private static final String END_OF_LINE = System.getProperty("line.separator");
        // you used "," many times - its called magic string or if some number
        // is jumping here and there in code its called magic number
        // when you define the variable then you change in ONE place when something changes
        private static final String COMMA = ",";
        // same here, name is stupid maybe, but it's better than ":" all around your code
        // rename it to something more meaningful
        private static final String DOUBLE_DOT = ":";
        private static final String EMPTY_STRING = "";

        // I don't like the name of the method, but ok, its a first iteration of refactoring
        private static String generateString(final Multimap<String, Info> reverseLookup) {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
        String splitThing = entry.getKey().split(DOUBLE_DOT);
        // I started to simplify and immediately seen you do split two times
        // while it could be done only once.. good catch
        // you might use some meaningful names, I just don't know much about your domain
        String something1 = splitThing[0]; // your doing split two times?
        // same here
        String something2 = splitThing[1];
        sb.append(something1).append(COMMA).append(something2).append(COMMA);

        createInfoString(sb, entry);

        sb.append(END_OF_LINE);
        }
        return sb.toString();
        }

        private static void createInfoString(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
        // I guess you've made it as the case to "" for first but "," for all next
        // I would probably go with for(int i=0; i<entry.length? ; i++){
        // separator = i == 0 ? EMPTY_STRING : DOUBLE_DOT;
        String separator = EMPTY_STRING;
        for (Info info : entry.getValue()) {
        sb.append(separator)
        sb.append(info.getLeafCategoryId())
        sb.append(DOUBLE_DOT).append(info.getScore());
        separator = COMMA;
        }
        }


        It's a first step, but looks a bit more clear for me.



        Now we do a bit more refactoring and its starts to get more clear what we do here



        public class DataFormatter {

        private static final String END_OF_LINE = System.getProperty("line.separator");
        private static final String COMMA = ",";
        private static final String DOUBLE_DOT = ":";
        private static final String EMPTY_STRING = "";
        private static final int NICE_PART_1_INDEX = 0;
        private static final int NICE_PART_2_INDEX = 1;

        private static String format(final Multimap<String, Info> reverseLookup) {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
        formatKey(sb, entry.getKey());
        formatValue(sb, entry);
        sb.append(END_OF_LINE);
        }

        return sb.toString();
        }

        private static void formatKey(StringBuilder sb, String key) {
        String splitThing = key.split(DOUBLE_DOT);
        String something1 = splitThing[NICE_PART_1_INDEX];
        String something2 = splitThing[NICE_PART_2_INDEX];

        sb.append(something1).append(COMMA).append(something2).append(COMMA);
        }

        private static void formatValue(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
        String separator = EMPTY_STRING;

        for (Info info : entry.getValue()) {
        sb.append(separator);
        sb.append(info.getLeafCategoryId()).append(DOUBLE_DOT).append(info.getScore());
        separator = COMMA;
        }
        }


        At the end, I added formatting code to class and called DataFormatter and format() method. If you would have formatting in 5 different places you could move them to this class, see common parts, reuse them rather than copy/paste similar code in many places.



        I would say - add unit tests which would pass any bad thing into your method you could imagine. Then you will be sure that your code works fine.






        share|improve this answer














        Ok, first of all. If you don't understand things right away, usually it means code is messy. Code gets messy when you don't have time to think and you just need to do it. I've refactored junior/mids code and even seniors code produced when people just want to do it right away and don't have time to think.
        So for the future. The way you approach is this is start simplifying, make the method do one thing. Get rid of repetitive parts.
        So with first iteration I refactored to this



        public class CategoryHolder {

        // when in your code you have System.getProperty() called many times - do you need that?
        // Its not changing every second, so when you store in variable, you're good then
        private static final String END_OF_LINE = System.getProperty("line.separator");
        // you used "," many times - its called magic string or if some number
        // is jumping here and there in code its called magic number
        // when you define the variable then you change in ONE place when something changes
        private static final String COMMA = ",";
        // same here, name is stupid maybe, but it's better than ":" all around your code
        // rename it to something more meaningful
        private static final String DOUBLE_DOT = ":";
        private static final String EMPTY_STRING = "";

        // I don't like the name of the method, but ok, its a first iteration of refactoring
        private static String generateString(final Multimap<String, Info> reverseLookup) {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
        String splitThing = entry.getKey().split(DOUBLE_DOT);
        // I started to simplify and immediately seen you do split two times
        // while it could be done only once.. good catch
        // you might use some meaningful names, I just don't know much about your domain
        String something1 = splitThing[0]; // your doing split two times?
        // same here
        String something2 = splitThing[1];
        sb.append(something1).append(COMMA).append(something2).append(COMMA);

        createInfoString(sb, entry);

        sb.append(END_OF_LINE);
        }
        return sb.toString();
        }

        private static void createInfoString(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
        // I guess you've made it as the case to "" for first but "," for all next
        // I would probably go with for(int i=0; i<entry.length? ; i++){
        // separator = i == 0 ? EMPTY_STRING : DOUBLE_DOT;
        String separator = EMPTY_STRING;
        for (Info info : entry.getValue()) {
        sb.append(separator)
        sb.append(info.getLeafCategoryId())
        sb.append(DOUBLE_DOT).append(info.getScore());
        separator = COMMA;
        }
        }


        It's a first step, but looks a bit more clear for me.



        Now we do a bit more refactoring and its starts to get more clear what we do here



        public class DataFormatter {

        private static final String END_OF_LINE = System.getProperty("line.separator");
        private static final String COMMA = ",";
        private static final String DOUBLE_DOT = ":";
        private static final String EMPTY_STRING = "";
        private static final int NICE_PART_1_INDEX = 0;
        private static final int NICE_PART_2_INDEX = 1;

        private static String format(final Multimap<String, Info> reverseLookup) {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String, Collection<Info>> entry : reverseLookup.asMap().entrySet()) {
        formatKey(sb, entry.getKey());
        formatValue(sb, entry);
        sb.append(END_OF_LINE);
        }

        return sb.toString();
        }

        private static void formatKey(StringBuilder sb, String key) {
        String splitThing = key.split(DOUBLE_DOT);
        String something1 = splitThing[NICE_PART_1_INDEX];
        String something2 = splitThing[NICE_PART_2_INDEX];

        sb.append(something1).append(COMMA).append(something2).append(COMMA);
        }

        private static void formatValue(StringBuilder sb, Map.Entry<String, Collection<Info>> entry) {
        String separator = EMPTY_STRING;

        for (Info info : entry.getValue()) {
        sb.append(separator);
        sb.append(info.getLeafCategoryId()).append(DOUBLE_DOT).append(info.getScore());
        separator = COMMA;
        }
        }


        At the end, I added formatting code to class and called DataFormatter and format() method. If you would have formatting in 5 different places you could move them to this class, see common parts, reuse them rather than copy/paste similar code in many places.



        I would say - add unit tests which would pass any bad thing into your method you could imagine. Then you will be sure that your code works fine.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Feb 6 at 4:45

























        answered Feb 6 at 4:19









        Sergii Nevydanchuk

        31428




        31428






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186168%2fgenerating-a-string-in-a-particular-format-by-reading-data-from-a-map%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Morgemoulin

            Scott Moir

            Souastre