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.
A Java programmer would iterate over an array as follows:
In Tcl, one could iterate over an array with:
String[] a = {"str1", "str2", "str3"};
for (int i=0; i < a.length; i++) {
String elem = a[i];
System.out.println("elem is " + elem);
}
Using the enhanced Java for syntax, one could iterate
over an array with the following code:
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"
}
The same iteration could be implemented in Tcl
using the java::for command:
String[] a = {"str1", "str2", "str3"};
for (String elem : a) {
System.out.println("elem is " + elem);
}
set a [java::new {String[]} {3} {str1 str2 str3}]
java::for {String elem} $a {
puts "elem is $elem"
}
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:
This same iteration could be implemented in Tcl, using
the java::for command.
Collection<String> c = MyJavaClass.getCollection();
for (String elem : c) {
System.out.println("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.
set c [java::call MyJavaClass getCollection]
java::for {String elem} $c {
puts "elem is $elem"
}
Multiple java::for commands can be used together
to iterate over all the elements of a multi-dimensional
array object.
The code above will print the following to the console:
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
}
}
1
2
3
4
5
6
7
8
9
Multiple java::for commands can be used together
to iterate over multiple collection objects.
The code above will print the following to the console:
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"
}
}
Black 0
Black 1
Black 2
White 0
White 1
White 2
The java::for command can be used to iterate
over elements in a Hashtable or any other Map implementation.
The code above will print the following to the console:
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"
}
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.
The code above will print the following to the console:
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"
}
s2 -> two
s1 -> one
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:
One could also iterate over the contents of this same Vector
as
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
}
java.lang.Integer
objects with the following code:
Both examples given above will write the same
output to the console.
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]
}
Copyright © 1997-1998 Sun Microsystems, Inc.