prabu
prabu

Reputation: 1277

Multiple toString methods?

I had a problem in generating a comma seperated string from a list of objects. The problem is explained in this link Convert string in list objects to comma separated

I had solved this by using toString method. Previously i was using the toString() method as string builder for debugging purpose. As i am using it for the generation of comma seperated value i could not debug it as before.

Is there anyway to accomplish both?

Upvotes: 2

Views: 13761

Answers (3)

Nathan Hughes
Nathan Hughes

Reputation: 96394

There ought to be a separate object to handle formatting. That's why you see formatting objects for dates and numbers in java.text, because there are so many different formats, you need dedicated formatters separate from the data objects.

Looking into what toString is for, the description given in the javadoc is

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

The Odersky/Spoon/Venners book Programming in Scala says:

The result of toString is primarily intended to help programmers by providing information that can be used in debug print statements, log messages, test failure reports, and interpreter and debugger output.

Also Effective Java (Item 10: Always Override toString) seems to assume that the purpose of toString is to provide diagnostic information to developers when debugging or logging.

I'd keep the implementation of toString you use for debugging and create a separate CSV-formatting object to deal with the csv generation. That way toString's purpose continues to be for debugging, separation of concerns is maintained between the object's job as a dataholder and CSV-generation.

Upvotes: 7

user180100
user180100

Reputation:

With some guava magic and lombok (for @Data):

@Data
public class Employee {
    private String name;
    private int age;
}

final List<Employee> employees = Lists.newArrayList(new Employee("Emp 1",25), new Employee ("Emp 2",25));
final List<Employee> names = Lists.newArrayList(Lists.transform(empList, new Function<Employee, String>() {
    @Override
    private String apply(final Employee e) {
        return e.getName();
    }
}));
// names = [Emp 1, Emp 2]
final String output = Joiner.on(", ").join(names);
// output = "Emp 1, Emp 2"

Note that the Function don't have to be an anonymous class and Employee has a generated usual toString() (from lombok).

Ref: guava, lombok

Upvotes: 0

Jeff Bowman
Jeff Bowman

Reputation: 95654

Other than adding processed strings (e.g. col5.getId() and user.getAddress().getAddress1()) to the list, which is probably the best and simplest answer, you could also write a wrapper that overrides toString:

public class AddressForCsv {
  private final Address address;

  public AddressForCsv(Address address) {
    this.address = address;
  }

  @Override public String toString() {
    return address.getAddress1();
  }
}

Then, add that wrapper object as your "column", and your data will show up appropriately.

Upvotes: 0

Related Questions