The java::for Command


Usage:

java::for type_var collection script

The java::for command provides a Tcl mapping to the enhanced Java for statement that appeared in JDK 1.5. The enhanced Java for statement can be used to iterate over a collection or over the elements of an array. The java::for command is like Tcl's foreach command, except that java::for works with a Collection object or a Java array object instead of a Tcl list or array. The java::for command does not require JDK 1.5 or newer, it works in any supported JDK version.

The type_var argument is a Tcl list that contains two elements. The first element is the type of the class, interface, or primitive type for the iteration variable. The second element is the name of the iteration variable.

The collection object is a handle to a Java array or a Java object that implements the java.util.Collection interface.

The script argument is evaluated once for each element in the collection. The iteration variable is set to an element in the collection before each evaluation of the script argument.

Examples:

Array Example:

The following example compares how one would iterate over an array in Java, in Tcl using a Java array handle, and in Tcl using the java::for command.

A Java programmer would iterate over an array as follows:

String[] a = {"str1", "str2", "str3"};

for (int i=0; i < a.length; i++) {
    String elem = a[i];
    System.out.println("elem is " + elem);
}
In Tcl, one could iterate over an array with:
set a [java::new {String[]} {3} {str1 str2 str3}]

for {set i 0} {$i < [$a length]} {incr i} {
   set elem [$a get $i]
   puts "elem is $elem"
}
Using the enhanced Java for syntax, one could iterate over an array with the following code:
String[] a = {"str1", "str2", "str3"};

for (String elem : a) {
    System.out.println("elem is " + elem);
}
The same iteration could be implemented in Tcl using the java::for command:
set a [java::new {String[]} {3} {str1 str2 str3}]

java::for {String elem} $a {
   puts "elem is $elem"
}

Collection Example:

The java::for command also supports iteration over any type of collection object. Assume for a moment that the user has defined a Java class. This class contains a static method that returns a collection object. The JDK 1.5 code to iterate over this collection would be:

Collection<String> c = MyJavaClass.getCollection();

for (String elem : c) {
    System.out.println("elem is " + elem);
}
This same iteration could be implemented in Tcl, using the java::for command.
set c [java::call MyJavaClass getCollection]

java::for {String elem} $c {
    puts "elem is $elem"
}
The reader will note that the type of the iteration variable is passed into the java::for command, just like the Java for statement. The java::for command uses this type information to check that the Java object extracted from the collection is of the expected type.

Multi-Dimensional Arrays:

Multiple java::for commands can be used together to iterate over all the elements of a multi-dimensional array object.

set a [java::new {int[][]} {3 3} {{1 2 3} {4 5 6} {7 8 9}}]

java::for {int[] asub} $a {
    java::for {int e} $asub {
        puts $e
    }
}
The code above will print the following to the console:
1
2
3
4
5
6
7
8
9

Multiple Collections:

Multiple java::for commands can be used together to iterate over multiple collection objects.

java::import -package java.util Vector
set v1 [java::new Vector]
set v2 [java::new Vector]

$v1 addElement [java::new String "Black"]
$v1 addElement [java::new String "White"]

$v2 addElement [java::new Integer 0]
$v2 addElement [java::new Integer 1]
$v2 addElement [java::new Integer 2]

java::for {String s} $v1 {
    java::for {int i} $v2 {
        puts "$s $i"
    }
}
The code above will print the following to the console:
Black 0
Black 1
Black 2
White 0
White 1
White 2

Elements in a Hashtable:

The java::for command can be used to iterate over elements in a Hashtable or any other Map implementation.

java::import -package java.util Hashtable Map
set t [java::new Hashtable]
$t put "One" "onestr"
$t put "Two" "twostr"

java::for {Map.Entry e} [$t entrySet] {
    set key [[$e getKey] toString]
    set value [[$e getValue] toString]
    puts "$key -> $value"
}
The code above will print the following to the console:
One -> onestr
Two -> twostr

The next java::for example shows how one could iterate over just the keys in a HashMap. The key could then be used to lookup the value.

java::import -package java.util HashMap
set t [java::new HashMap]
$t put "s1" "one"
$t put "s2" "two"

java::for {String key} [$t keySet] {
    set value [[$t get $key] toString]
    puts "$key -> $value"
}
The code above will print the following to the console:
s2 -> two
s1 -> one

Automatic Type Conversion:

The java::for command supports automatic conversion of a Java primitive wrapper in a collection to a Tcl value. For example, a Vector of java.lang.Integer objects can be iterated over as Tcl integers with the following code:

set v [java::new java.util.Vector]
$v addElement [java::new Integer 0]
$v addElement [java::new Integer 1]
$v addElement [java::new Integer 2]

java::for {int e} $v {
    puts $e
}
One could also iterate over the contents of this same Vector as java.lang.Integer objects with the following code:
set v [java::new java.util.Vector]
$v addElement [java::new Integer 0]
$v addElement [java::new Integer 1]
$v addElement [java::new Integer 2]

java::for {Integer e} $v {
    puts [$e toString]
}
Both examples given above will write the same output to the console.


Copyright © 1997-1998 Sun Microsystems, Inc.