Multiple Type Dictionaries

In processing, is there a way to have a dictionary with multiple types (e.g. String, int, float, etc)

I can’t seem to find if there is or not in the docu, the best I’ve found is single type ones like a float dict, int dict, etc

Many thanks

1 Like
2 Likes

As @GoToLoop indicated, a HashMap with values of type Object will do this. It is often a bad idea – most often, wanting to do this indicates a problem with the design – but not always.

If all you need to do in the end is print your object then no casting is required. If you plan to operate on your objects by type, then you can use instanceof to find those entries with e.g. Integer or String values, and act only on those entries (or act on those values only in certain ways).

/**
 * HashMapObject - example hashmap with mixed value types
 * 2019-11-29 Processing 3.4 - Jeremy Douglass
 */
import java.util.Map;
HashMap<String, Object> hm;

void setup() {
  hm = new HashMap<String, Object>();
  hm.put("one", 1);      // new Integer(1)
  hm.put("two", "two");  // new String("two")
  hm.put("three", PI);   // new Float(PI)

  // print map
  //   {one=1, two=two, three=3.1415927} 
  println(hm, "\n");

  // print values
  //   1  two  3.1415927  
  for (Object val : hm.values()) {
    print(val, " ");
  }
  println("\n");

  // print keys and values
  //   one: 1
  //   two: two
  //   three: 3.1415927
  for (Map.Entry me : hm.entrySet()) {
    print(me.getKey() + ": ");
    println(me.getValue());
  }
  println("");

  // sum all Integers or Floats
  //   4.141593
  float sum = 0;
  for (Object val : hm.values()) {
    if (val instanceof Integer) sum += (Integer)val;
    if (val instanceof Float)   sum += (Float)val;
  }
  println("sum of integers: ", sum, "\n");

  // get first letter of any String
  //   t
  for (Object val : hm.values()) {
    if (val instanceof String) println(((String)val).charAt(0), "\n");
  }

  // get a specific key "one" and handle it based on type
  //   1.234567
  Object val = hm.get("one");
  if (val instanceof Integer) println((Integer)val + 0.234567);
  else println("not an Integer");
}

Again, most of the time this is a bad idea. Instead, you should be storing your data in structured ways based on type. Still, mixing types on the fly can sometimes be useful. A scenario where this might make sense is large sparse semi-structured field sets of different types – like a test bank of quiz questions with different answers (“owl”, “3.14”), or an Amazon product page, which might have (but does not necessarily have) keys for count, width, weight, expiration, ISBN, minimum age, allergy-information, nation of origin, etc. etc. – and those fields might have values of all kinds, like strings, dates, integers, floats, et cetera.

That sounds a bit like a row in a spreadsheet – as many cells as you want, each configurable to a different type. In fact, Processing’s Table (and the interface TableRow) is implemented on top of an Object[] columns. Depending on your needs, Table might be a great way to define and assemble lists of mixed types and then retrieve them. If you don’t really want columns, however, HashMap<E, Object> keeps it simple – it just requires casting to manipulate the retrieved values.

2 Likes