Skip to main content

Primitive Collections

6 replies [Last post]
markf
Offline
Joined: 2005-01-20
Points: 0

A nice new language feature would be more support for primitive collections.

Considers Python this wonderfully clean python code for creating a dictionary:

<br />
ages = {"Fred" : 35, "Jennifer" : 27, "Bob" : 58, "Carol" : 41 };<br />
Compare that to Java's somewhat less pleasant:
<br />
ages = new HashMap();<br />
ages.put("Fred", 35);<br />
ages.put("Jennifer", 27);<br />
ages.put("Bob", 58);<br />
ages.put("Carol", 41);<br />
Of course, there's also the problem of it having to wrap the numbers, wasting space and time.

We already have one primitive collection type -- arrays, which are a primitive corallary of Lists. This suggests similar corallaries for sets and/or maps. This could necessitate adding "in" as a keyword. I'd love to see something in Java like:

<br />
/* based on Java's syntax for initializing arrays<br />
and python's syntax for initializing dictionaries. */<br />
String:int ages = new String:int {"Fred" : 35, "Jennifer" : 27, "Bob" : 58, "Carol" : 41 };<br />
assert 35 == ages["Fred"];<br />
assert "Fred":35 in ages;<br />
assert "Fred" in ages.keys;<br />
assert 35 in ages.values;</p>
<p>long:int reverseFactorial = new long:int {1 : 1, 2 : 2, 6 : 3, 24 : 4, 120 : 5, 720 : 6, 5040 : 7, 40320 : 8};</p>
<p>/* combined with hypothetical tuple syntax. */<br />
(int,int):int powers = new (int,int):int {(2,1) : 2, (2,2) : 4, (10,3) : 1000};<br />
assert 2 == powers[(2,1)];<br />
assert (10,3):1000 in powers;<br />
assert (10,3) in powers.keys;<br />
assert 1000 in powers.values;</p>
<p>/* hypothetical multidimensional map, similar to<br />
the idea of multidimensional arrays. */<br />
String:String:int households = new String:String:int {<br />
    "11 Williams st" : {"John" : 34, "Carol" : 32, "Sally" : 8},<br />
    "10118 W Pender ave" : {"Alice" : 23},<br />
    "28 Williams st" : {"Frank" : 51, "Lance" : 55},<br />
};<br />
assert "John" in households["11 Williams st"].keys;<br />
assert 51 == households["28 Williams st", "Frank"];<br />
Anyway, what do people think? Does the idea have any value, or should we just stick with using gnu.trove?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
vpatryshev
Offline
Joined: 2004-06-30
Points: 0

Good idea.

I've been thinking of something much humbler: say, just an ability to initialize a map during creation. Not being a big fan of language changes. How could one do it? The only legal way in Java would be something like this:

[code]
Map m = makeMap(
new Pair[] {
new Pair("Fred",35),
new Pair("Jennifer",27),
new Pair("Bob",58),
new Pair("Carol",41)});
[/code]

Looks ugly... But if there were something like a tuple creation primitive, then we could write

[code]
Map m = makeMap(
{{"Fred",35},
{"Jennifer",27},
{"Bob",58},
{"Carol",41}});
[/code]

And the type could be inferred from the values. Instead of "checking". I would prefer this to a more specific map creator.

tackline
Offline
Joined: 2003-06-19
Points: 0

If you are in a situation that requires many hard-coded maps, you may find a method similar to the following useful:

public static Map makeMap(
Class keyClass, Class valueClass, Object... keyValues
) {
final int num = keyValues.length;
if (num%2 != 0) {
throw new IllegalArgumentException(
"Required even number of key/values. "+num+" is odd."
);
}
if (num == 0) {
return Collections.emptyMap();
}
if (num == 2) {
return Collections.singletonMap(
keyClass.cast(keyValues[0+0]),
valueClass.cast(keyValues[0+1])
);
}
// For small maps,
// you may want a different implememtation such as TreeMap.
// Initial capacity easily enough so as to not resize.
Map map = new HashMap(num*3/2 /2);
for (int ct=0; ct map.put(
keyClass.cast(keyValues[ct+0]),
valueClass.cast(keyValues[ct+1])
);
}
return Collections.unmodifiableMap(map);
}

The previous poster's example can now be written:

Map nameAgeMap = makeMap(
String.class, Integer.class,
"Fred", 35,
"Jennifer", 27,
"Bob", 58,
"Carol", 41
);

Two tokens less than heavily modifying the language! And we could drop the .class business in exchange for more dynamic type-safety.

vpatryshev
Offline
Joined: 2004-06-30
Points: 0

http://www.myjavatools.com/projects/v.5.0/lib/doc/com/myjavatools/lib/foundation/Maps.html#arrayToMap(java.lang.Object[])

mgrev
Offline
Joined: 2003-08-12
Points: 0

I actually think the Java syntax is more clean, and it's only a few characters longer.

If you have a lot of places where you produce these kinds of maps, why not make a builder class?

However, I think that Generics should have been implemented to produce real primitive versions of the generified classes insted of calsing at runtime. But that's another story.

Cheers,
Mikael Grev

vpatryshev
Offline
Joined: 2004-06-30
Points: 0

Wait, autoboxing already does it in Java, does not it? And with generics, it is pretty easy to mix them up, primitives and wrapper classes, without even notcing.

kcpeppe
Offline
Joined: 2003-06-15
Points: 0

Autoboxing is a horrible hack.... I would much prefer a normalization of primitives and objects similiar to what has been suggested.