JavaFX sequences can be described as being analogous to arrays in other languages. Imagine that you want to keep track of a group of items of the same type (say a list of numbers, for instance). You can use a sequence to store that list of items and manipulate the list with operations such as insert, query, and item removal. This section looks at how to create and work with JavaFX sequences.
You should be familiar with the concepts of array, list, and map data types. These are common types found in all popular languages. They are designed to function as a container of other values of arbitrary types.
A sequence type is declared using a non-sequence type followed the square brackets "[ ]". Below are some literal declarations of sequences. You can get full listing of the code from ch01/source-code/src/javafx/SequenceType.fx and Sequence.fx
.
var numbers:Number[] = [10.0,5.6,12.3,0.44]; var numbers2 = [0,2,3,4,5,6,7,8]; var notes:String[] = ["Avion","Airplane"]; var timespans = [5s,3m,100s,5m]; var misc = [2,4.0,"messages", 5m];
Sequence types represent a collection of other types in JavaFX. Sequences provide a flat (depth of one) container where you store references to other objects. A sequence is a first-class type in JavaFX. Therefore, it has a return type and can participate in expressions.
JavaFX supports a initialization of sequence types using literal declaration which provides a more natural way of representing the sequence. The literal expression for the sequence shows each item in the sequence separated by a comma as shown below:
var numbers:Number[] = [10.0,5.6,12.3,0.44];
The type inference engine will attempt to determine the type of the sequence variable based on the types of the items within the square brackets.
If all items within the bracket of the literal declaration are of the same type, the variable is coerced into a sequence of that type. For instance, the following example, variable numbers2
is of type Integer[]:
var numbers2 = [0,2,3,4,5,6,7,8];
If items within the brackets are of different types, the inference engine will coerce the variable to be of type Object[]
. In the following code snippet, variable misc
will be of type Object[]
and can receive member of any type:
var misc = [2,4.0,"messages", 5m];
Similar to Java arrays, items in a sequence are referenced using a zero-based positional index. Sequence items are stored in order they are added (or declared) as shown in the snippet below from ch01/source-code/src/javafx/Sequence.fx
.
var q1 = ["Jan", "Feb", "Mar"]; println (q1[0]); println (q1[1]); println (q1[2]);
Sequences come with several other important features worth mentioning here. Although the literal representations of sequences looks like an array, that is where the similarity ends. Sequences support several data management operations such as insert, union, query, and delete. As you will see below, sequence expressions can also be used as generators in JavaFX loops. The code samples are from script file ch01/source-code/src/javafx/Sequence.fx
.
JavaFX sequences support several operators:
sizeof operators return the size when applied to a sequence.
sizeof [1,2,3,4];
Comparison JavaFX sequences can be tested for deep equality. This means that two sequences are the same if they are of the same size and contain the same items. The statement below will print true
println([1,2,3,4] == [4,3,2,1])
Reverse this operator automatically reverses the order in which items are referenced in a sequence.
println(reverse ["Jan", "Feb", "Mar", "Apr");
JavaFX sequences also support operations to manipulate sequences and sequence items directly.
Insert Operation as the name implies, this operation inserts item(s) into a given sequence. The following example shows all of the supported form of insert
.
var months = ["Jan"]; insert "May" into months; insert ["Mar","Apr"] before months[1]; insert "Feb" after months[0];
Besides the into
directive, note that the insert operation support a before
and after
clause which specifies the location (index) where the item is to be inserted.
Union sequences can be nested using literal declaration to create new lists:
var q1 = ["Jan", "Feb", "Mar"]; var h1 = [q1, ["Apr", "May", "Jun"]];
Delete Operation the delete
operation removes items from a given sequence. The following example shows the supported forms of delete.
var months = ["Jan", "Feb", "Mar", "Apr", "May"]; delete "May" from months; delete months[3];
Note
It is critical to understand that sequences are immutable, meaning that the values in a sequence do not change. Rather, any modification to a sequence (insert, delete, and so on) generates a new sequence object to reflect the modification desired.
When deleting by value (that is, delete "May" from months)
, all items of same value will be removed from the sequence.
Sequence slice notations are used to generate subsets of larger sequences. Given this sequence
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"];
Here are some slice operations supported by JavaFX:
months[1..4]
returns a sequence["Feb", "Mar", "Apr", "May"]
months[0..<3]
returns sequence[ "Jan", "Feb", "Mar"]
months[3..]
returns sequence["Apr", "May", "Jun"]
months[0..<]
returns sequence["Jan", "Feb", "Mar", "Apr", "May"]
Sequence Projection you can use constraint expressions to project sub-sequences on a given sequence using format sequence[x | {Boolean expression}]
. This notation reads as "select all element x
where the Boolean expression is true".
: months[m|m.startsWith("M")]
The above code returns sequence ["Mar", "May"]
from var months
declared previously. This expression creates slices based on given arbitrary Boolean condition. It reads as "for all item m in months where m
starts with M.
"
The loop structure is used to query elements in sequences to create subsets based on conditional expressions. The general format is:
for (x0 in seq0 [where {Boolean expression}][, queryn]){}
The loop expression can use a where
clause along with a Boolean expression to filter down to specific elements to build the subset. A simple example is:
var points = [1,2,3,4,5,6,7,8,9,10,11,12,13,14]; var evenPoints = for(n in points where n mod 2 == 0) {n} println (evenPoints);
In the previous code, the loop generates a new sequence with only even members from the original sequence, [ 2, 4, 6, 8, 10, 12, 14 ]
, using the where
clause to specify a selection expression.
Also notice you can add more than one query in the loop expression where the result is a Cartesian product of all subsets expressed in each query. For instance, the following will produce 14 elements
var doublePoints = for(n in points where n mod 2 == 0, i in [2,4]){ n * i } println (doublePoints);
This code loops over two sequences; the first sequence contains all even members of the original points variable declared previously; the other is a two-member sequence containing 2 and 4, the loop generates new sequence [ 4, 8, 8, 16, 12, 24, 16, 32, 20, 40, 24, 48, 28, 56 ]
.