简体   繁体   中英

How to print an object which points to an array in Java

I have a map which is defined like

HashMap<Object, Object> hashMap;

Now I need to iterate over each pair and print the key and value. Doing key.toString() and value.toString() works well for types like ArrayList . But toString() on an array won't give a readable string.

I am aware about Arrays.toString() . But I can't use it in my case because Arrays.toString() expects an object array and all I have is an object. So I wrote a custom code which looks like,

private String convertToHumanReadableFormat(Object value) {
    if (value == null) return "N/A";
    if (value.getClass().isArray()) {
        return convertArrayToReadableFormat(value);
    }
    return value.toString();
}

private String convertArrayToReadableFormat(Object value) {
    String output = "[";
    int arrayLength = Array.getLength(value);
    for (int i = 0; i < arrayLength; i++) {
        Object element = Array.get(value, i);
        if (element != null) {
            if (element.getClass().isArray()) {
                output += convertArrayToReadableFormat(element);
            }
            else {
                output += element.toString();
            }
        }
        if ((i + 1) < arrayLength)
            output += ", ";
    }
    output += "]";
    return output;
}

I am actually duplicating what Arrays.deepToString() does. But I can't see a way to just use Arrays.toString() or Arrays.deepToString() .

Is this the correct approach to the problem or is there any way to get those standard methods working for me?

Any help would be great.

Please modify the method convertToHumanReadableFormat to the following. I have tested it and it indeed worked.

private <T> String convertToHumanReadableFormat(Object value) {
            if (value == null) return "N/A";
            if (value.getClass().isArray()) {
                if( value instanceof int[]||value instanceof long[]){
                    List<T> list = new ArrayList<T>();
                    list.addAll((Collection<? extends T>) Arrays.asList(value));
                    return convertToHumanReadableFormat(list.toArray());

                }else{
                     return Arrays.deepToString((Object[]) value);
                }
            }
            return value.toString();
        }

You can add other primitive types to the if condition.

what if you convert array to list and then use toString -

Arrays.asList(array)

you will need to write your helper method this way -

private String convertToHumanReadableFormat(Object value) {
    if (value == null) return "N/A";
    if (value.getClass().isArray()) {
       value = Arrays.asList((Object[])value);     
    }     
    return value.toString(); 
} 

to handle primitives you will need to first manually convert array to list -

private String convertToHumanReadableFormat(Object value) {
    if (value == null) return "N/A";
    if (value.getClass().isArray()) {

       //convert array to list 
       int count = Array.getLength(value);
       ArrayList<Object> list = new ArrayList<Object>();
       for(int i=0; i<count; i++){
          list.add(Array.get(value, i));
       } 
       return list.toString(); //or value=list;  
    }     
    return value.toString(); 
}

There are several approaches you can consider -
A. If you're not to strict on the format, and just want to print the HashMap contents in a human readable way, I would suggest you to use JSon serializing - the output if quite human readable.
You can see what we did at Ovirt open source project (clone the git repo of the engine project) - engine\\backend\\manager\\modules\\utils\\src\\main\\java\\org\\ovirt\\engine\\core\\utils\\serialization\\json - look at the JsonObjectSerializer class there.

B. If you are strict on the format - You should get the entrySet of your map, iterate over it, and insert the objects into an ArrayList . After that you can use the toArray() method to return an array, and use the method you described above.
Bare in mind that I suggest that your ArrayList will be an ArrayList of Strings, so you must take each mapEntry and translate it string, consider the toString() and see if the format it produces is good enough for you.

If you use case is rendering arrays and other object graphs in human readable form you may go for templating solution (like velocity of freemarker) or convert them to JSON (or XML) and rpetty pring it - I would recommend GSON / XStream for this task.

If you like to have it for debug purposes, then just stick with logging system and use standart converters available there ( for example in log4j)

You could just use nine instanceof statements to call the appropriate toString or deepToString method. If you do use your own code, remember to use a StringBuilder and to take into account the possibility of an array containing a reference to itself or a parent dimension. Currently your code would recurse until stack overflow. Using instanceof as I suggest would also avoid the boxing of primitive values that is inherent in your code (and thus improve performance). Nine statements isn't too many, is it?

if (val instanceof Object[]) return Arrays.deepToString((Object[]) val);
if (val instanceof byte[]) return Arrays.toString((byte[]) val);
// Repeat for other 7 array types...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM