A JavaFX Script sequence is a special kind of data structure that, like an array in Java, represents an ordered list of items of the same type. But unlike Java arrays, JavaFX Script sequences are not objects. Like arrays, however, they hold elements (individual items in the sequence) of the same type.
Syntax
varsequence_name
:datatype
[];
or
varsequence_name
:datatype
[] = [value1
,value2
..value n
];
or
var sequence_name = [value1, value2 .. value n];
The examples in Listing 10-1 show several ways to create and initialize a sequence.
Example 10.1. Different ways of defining a sequence
1. var emptySequence : Integer[]; 2. println(emptySequence); // [] 3. 4. var intSequence : Integer[] = [2,4,6,8,10]; 5. println(intSequence); // [ 2, 4, 6, 8, 10 ] 6. 7. var inferenceSequence = ["Praveen", 'Girish' ,"Cheran" , 'Rabi' , "Lawrence" ]; 8. println(inferenceSequence); // [ Praveen, Girish, Cheran, Rabi, Lawrence ]
In line 1 we create an empty sequence, which is represented as brackets: [ ]
. In line 4 we define an Integer sequence named intSequence
and initialize it. As you can see, a sequence is initialized by specifying its elements within the brackets. In line 7, we define an Inference-type sequence called inferenceSequence
; this sequence holds String elements.
After creating a sequence, we commonly need to know the number of elements it holds. So JavaFX Script provides a unary operator called sizeof
, which returns the number of elements in a sequence.
Syntax
sizeof sequence name
;
The example in Listing 10-2 demonstrates the usage of the sizeof
operator.
Example 10.2. Using the sizeof operator
1. var emptySequence:Integer[]; 2. println("sizeof emptySequence = {sizeof emptySequence }"); // sizeof emptySequence = 0 3. 4. var inferenceSequence = ["Praveen",'Girish', "Cheran" , 'Rabi' , "Lawrence" ]; 5. println("sizeof inferenceSequence = {sizeof inferenceSequence}"); // sizeof inferenceSequence = 5
Line 2 prints 0 for emptySequence
, since it doesn't have any elements, and line 5 prints the size of inferenceSequence
as 5, since that variable holds five elements.
Once you create a sequence, you may need to access its elements, either in a specific order, such as from the first element to the last, or randomly. You access an element of a sequence by specifying its index within square brackets ([ ]).
Syntax
sequence_name
[index
] ;
The example in Listing 10-3 demonstrates how to access the elements of a sequence.
Example 10.3. Accessing the elements of a sequence
1. var teamMembers : String[] = [ 2. "Praveen", "Lawrence", "Girish","Rabi","Cheran","Srini","Blessan" 3. ]; 4. println("My team members"); // My team members 5. for( i in [0.. sizeof teamMembers - 1] ) 6. println(teamMembers[i]); // Praveen Lawrence Girish Rabi Cheran Srini Blessan
In Listing 10-3, we declare a String sequence teamMembers
. E
ach element of the sequence is accessed using its index, as in line 12. To access the element, we have used a for
range expression, which starts from zero and ends with sizeof teamMembers −1
.
Alternatively, you can use the following statements to access the elements of the sequence:
for( i in names ) println(i);
Elements of a sequence can also be accessed randomly. For example, if you want to access the third element of the teamMembers
sequence, you specify it as teamMembers[2]
, which returns the value girish
.
Sequences are "zero based," which means they always starts from zero and end with a value of sizeof the sequence minus 1. For example, if the sequence has 100 elements, the first element is accessed by sequence[0] and the last element by sequence[99].
You might come across a situation where you need to combine sequences. When you do this, the JavaFX Script compiler automatically flattens all the sequences to form a single sequence.
The example in listing 10-4 demonstrates the nesting of sequences.
Example 10.4. Sequence nesting
1. var numSeq1 : Integer[] = [1,2,3]; 2. var numseq2 : Integer[] = [6,7,8,9,10]; 3. var numSeq3 : Integer[] = [ numSeq1 , 4,5, numseq2 ]; 4. println(numSeq1); // [ 1, 2, 3 ] 5. println(numSeq2); // [ 6, 7, 8, 9, 10 ] 6. println(numSeq3); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
First we declare three sequences. The last sequence (numSeq3
) holds numSeq1
and numSeq2
as individual elements (to form a nested sequence), as well as its own elements. When JavaFX Script executes line 3 it flattens numSeq1
and numSeq2
to form a single sequence, (numSeq3
). This can be seen in the line 6 output statement.
Range expressions can be used to create either Integer or Number sequences. You have already seen range expression in Chapter 4, "Operators and Expressions." Usually a range expression consists of a starting number, ending number, and optional step value. The step value may be either positive or negative (depending on the requirement); the default step value is 1.
Syntax
varsequence_name
:datatype
[] = [start value ..end value step value
];
The example in Listing 10-5 demonstrates how to create sequences using range expressions.
Example 10.5. Creating sequences using range expressions
1. var intSeq : Integer[] = [1..10]; // default step positive 1 2. println(intSeq ); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 3. var intSeq1 : Integer[] = [0..100 step 10]; // step 10 4. println(intSeq1); // [ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ] 5. var emptySeq : Integer[] = [100..0]; //empty sequence, since step is missing 6. println(emptySeq); // [ ] 7. var intSeq2 : Integer[] = [100..0 step −10 ]; 8. println(intSeq2); // [ 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0 ] 9. var numSeq : Number [] = [0.5 .. 5.0 step 0.5]; // number sequence 10. println(numSeq); // [ 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0 ]
In line 1, we declare an intSeq
sequence whose value ranges from 1 to 10. Since we have not specified the step value, its default value of 1 is used. In line 3, we declare an intSeq1
sequence, whose value ranges from 0 to 100 with a step value of 10. Next, in line 5, we declare an emptySeq
sequence, whose range of values is from 100 to 0. Since the starting number of the range is greater than the end number and we have not specified the step value of this sequence, the result of this range expression is zero; hence, the sequence is empty. To avoid this type of empty sequence creation, it is mandatory to specify the step value of the range expression used to create the sequence. The correct version of the empty sequence is specified in line 7, with the sequence creation intSeq2
. Finally, line 9 shows a Number
sequence whose range value is from 0.5 to 5.0 with the step value of 0.5.
When you compile the code in Listing 10-5, you will encounter a warning that the expression will return an empty sequence.
It's a good practice to specify the step value when creating a sequence using a range expression.
Until now, the sequences that you have created using range expressions included the end value that you specified in the range expression. In some situations, you may need to exclude the end value when creating a sequence using a range expression. To do this, use two dots and a less-than relation operator (..<
) in the range expression.
Syntax
varsequence_name
:datatype
[] = [start value .. end value step value
];
The example in Listing 10-6 demonstrates how to create a sequence that excludes the end value of its range expression.
Example 10.6. Creating a sequence that excludes the end value of the range expression
1. var intSeq : Integer[] = [1..< 10]; 2. println(intSeq ); // output [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] 3. var intSeq1 : Integer[] = [0..< 90 step 10]; 4. println(intSeq1); // output [ 0, 10, 20, 30, 40, 50, 60, 70, 80 ]
In this example, we declare two sequences and create them using range expressions. In line 1, we have a range expression generating numbers from 1 to 10. While generating the range numbers from 1 to 10 each time, the JavaFX Script compiler checks the condition that generated numbers must be less than 10. Once the generated number reaches 10, then your range expression is stopped, since the condition has failed and the resulting sequence range is from 1 to 9. In line 3, we declare a sequence whose range number is from 0 to 80 with the specified step value of 10. This sequence holds the decade values from 0 to 80, since the condition for this range expression is < 90 and the step value is 10.
Sequence slicing provides access to portions of a sequence. That is, using this technique you create from an existing sequence either a new sequence or an expression that evaluates to a sequence. The newly created sequence elements will be within the range, or equal to the existing elements, of the existing sequence. Usually sequence slicing consists of a sequence name (the existing sequence) or another expression that evaluates to a sequence, followed by a pair of square brackets which has a starting index with an optional ending index separated by two dots (..) or two dots with a less-than relational operator (..<
). If the ending index is omitted, JavaFX Script interprets it as accessing all the elements of the sequence started from the specified starting index to the sizeof
the sequence minus one.
The example in Listing 10-7 demonstrates sequence slicing.
Example 10.7. Sequence slicing
1. var s1 = [0..8]; // [0,1,2,3,4,5,6,7,8] 2. var s2 = s1[4..]; 3. println(s2); // [4,5,6,7,8] 4. var s3 = s1s2[0..<]; 5. println(s3); // [0,1,2,3,4,5,6,7 ]
In line 1, we declare a sequence s1, which holds the values from 0 to 8. In line 2, we are creating a new sequence (s2) from s1, and we are instructing the JavFX Script compiler to access all the elements of sequence s1
starting from index 4 to the sizeof s1
minus one. In line 4 we are creating a new sequence s3
from s2
, in which we access all the elements of s2
starting from index 0 to the last element of s2
sequence; that is, from s2[0]
to s2[sizeof s2-1]
.
A predicate is a Boolean expression used to create a new sequence that is a subset of an existing sequence.
Syntax
varnewSequence = existingSequence
[variable
|Boolean expression
];
Here, existingSequence
is the name of the existing sequence from which you are going to create a new sequence, which will be a subset of existingSequence
, and assign it to newSequence
. Notice the pair of square brackets ([ ]) that enclose a predicate in the format of a selection variable. Here, variable
is just a placeholder within the square brackets that helps the compiler to evaluate Boolean expression.
The vertical bar | character is used to visually separate the variable from Boolean expression.
Finally, the Boolean expression
specifies the criteria to be met before the current item will be copied into the new sequence.
The example in Listing 10-8 demonstrates creating a new sequence from an existing sequence using predicates.
Example 10.8. Creating a new sequence from an existing one using predicates
1. var integerSequence : Integer[] = [1..10 ]; 2. println(integerSequence); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 3. var subSequence1 = integerSequence[ n | n > 5 ]; 4. println(subSequence1); // [ 6, 7, 8, 9, 10 ] 5. var subSequence2 = integerSequence[ n | n < 5 ]; 6. println(subSequence2); // [ 1, 2, 3, 4 ] 7. var subSequence3 = integerSequence[ n | indexof n > 4 ]; 8. println(subSequence3); // [ 6, 7, 8, 9, 10 ] 9. var subSequence4 = integerSequence[ n | indexof n < 2 or indexof n > 7 ]; 10. println(subSequence4); // [ 1, 2, 9, 10 ] 11. var emptySequence = integerSequence[ n | n > 10 ]; 12. println(emptySequence); // [ ]
The difference between sequence slicing and sequence predicates is that in sequence slicing, a range expression is used to create a new sequence, whereas in sequence predicates the vertical bar and a Boolean expression are used to create a new sequence from an existing one.
So far, you have created sequences either by explicitly specifying the elements of the sequence or by using range expressions. JavaFX Script also allows you to insert and delete the elements of the sequence dynamically. The following operations can be performed on a sequence:
Inserting elements into the sequence
Deleting elements from the sequence
Reversing a sequence
An element can be inserted into a sequence dynamically using the insert
and into
keywords.
Syntax
insertelement
intosequence_name
; var seq : Integer [] ; insert 120 into seq; insert 45 into seq;
In these statements we first create an empty Integer sequence, seq
. in the later statements we insert the values 120 and 45 into the seq
sequence. By default, elements are inserted at the end of a sequence. So when you print the seq
sequence, you see the following output on the console:
[ 120 , 45 ]
Suppose you want to insert an element 75 as the first element of the sequence seq
. To do that, you can use the following syntax:
Insertelement
beforesequence_name
[ index ] ; insert 75 before seq[0]; insert 99 before seq[2];
In these statements, we are inserting the value 75 as the first element (seq[0]
) and value 99 as the third element ( seq[2]
). We do this by using the keyword before
and specifying the index within the sequence where we want to insert. The before
keyword instructs JavaFX Script that you need to insert the element before the specified index in the sequence. When you print this seq
sequence, you'll see the following output on the console:
[ 75, 120, 99, 45 ]
You can insert an element after a specified element in a sequence; this is done using the keyword after
.
Syntax
insertelement
aftersequence_name
[index
];
For example, in the following statements:
insert 67 after seq[1]; insert 78 before seq[1];
we are inserting 67 as the third element and 78 as the last element of the sequence seq
. The final output of the seq
sequence is as follows:
[ 75, 120, 67, 99, 45, 78 ]
An element or value can also be inserted into a sequence by specifying a negative index.
The examples in Listing 10-9 show how to insert elements into a sequence by specifying the index in different forms.
Example 10.9. Different ways of inserting elements into a sequence dynamically
1. var nums = [0..10]; 2. insert 65 after nums[sizeof nums+1]; 3. insert 23 after nums[sizeof nums]; 4. insert 77 after nums[sizeof nums - 1]; 5. insert 21 before nums[5]; 6. insert 97 after nums[0]; 7. insert 6 before nums[-1]; 8. insert 54 after nums[-2]; 9. println(nums); // [ 54, 6, 0, 97, 1, 2, 3, 4, 21, 5, 6, 7, 8, 9, 10, 65, 23, 77 ]
We are not restricted to inserting only a single element into a sequence; we can also insert a sequence into an existing sequence. The resulting sequence will be flattened, as you learned in the "Nested Sequences" section of this chapter.
The example in Listing 10-10 demonstrates how to insert a sequence as an element into another sequence.
Example 10.10. Inserting a sequence as an element into a sequence
1. var num : Integer[] = [1..4]; 2. var num1 : Integer[] = [5..10]; 3. insert num1 after num[2]; 4. println(num); // [ 1, 2, 3, 5, 6, 7, 8, 9, 10, 4 ]
In this example, we declare two sequences, num
and num1
, using range expressions. In line 3 , we are inserting the num1
sequence after num[2]
.
Element of a sequence can be deleted dynamically, using the delete
keyword. Following are different ways of deleting elements from a sequence:
Syntax
deleteelement
fromsequence_name
; deletesequence_name
[index
];
The examples in Listing 10-11 demonstrate various ways of deleting elements from a sequence.
Example 10.11. Ways of deleting elements from a sequence
1. var fruits : String [] = ["Applet" , "Mango" , "Orange", "Grapes"]; 2. delete "Mango" from fruits; // deleting the element by specifying the element itself. 3. delete fruits[1]; // deleting the element by specifying the index of the element 4. println(fruits); // [ Applet , Grapes ]
In line 1, we declare a String sequence named fruits
with four elements. In line 2, we are deleting an element Mango
from the sequence fruits
; here from
is a keyword that specifies from which sequence you are deleting the element. In line 3 , we are deleting the element by specifying its index within the sequence.
You can delete all of the elements in the sequence by specifying just the delete
keyword followed by the sequence name, as in this example:
var fruits : String [] = ["Applet" , "Mango" , "Orange", "Grapes"]; delete fruits ;
Alternatively, you can use the following statement to delete all the elements of the sequence:
fruits = [];
You have learned how to create an Integer or Number sequence using a range expression. However, there may be situations where you need to delete a portion, or subset, of the sequence. In the previous the example of the fruits
sequence, if you need to delete all the elements except Grapes
, you can use the following statements:
delete fruits[0..2];
The delete
command only removes elements from the sequence; it does not delete the sequence from your script. You can still access the sequence and add new items to it as before.
JavaFX Script provides the reverse
operator to reverse the order of elements in a sequence. The reverse
operator produces a new sequence that contains the same elements as the original sequence but in reverse order.
Syntax
var sequence = reverse existingSequence;
The example in Listing 10-12 demonstrates how to reverse a sequence.
Example 10.12. Reversing a sequence
1. var namesSeq : String[] = ["Lawrence" , "Yinhe" , "Praveen" , "Vimala Anne"]; 2. var reversedNameSeq = reverse namesSeq; // returns the reversed sequence of namesSeq 3. println(reversedNameSeq); // [ Vimala Anne, Praveen, Yinhe, Lawrence ]
Here, line 2 returns the reverse of sequence nameSeq
to reversedNameSeq
. This new sequence has the same elements as namesSeq
but in the reverse order.
Unlike Java and its handling of arrays, JavaFX Script allows sequences to be used as function parameters. When a sequence is sent as a parameter to a function, its elements are read-only, like any other parameter to the function. That is, trying to change the elements of the sequence, inserting and deleting them dynamically, will result in a compile-time error. A script-level, package-level sequence can be accessed by any function. Sequences defined within a function, by contrast, cannot be accessed outside the function.
The example in Listing 10-13 demonstrates the implementation of a stack using a sequence; the sequence is passed as a parameter to the function.
Example 10.13. Implementing a stack using a sequence, by passing the sequence as a parameter to the function
1. var stack: Integer[]; 2. function push(value : Integer){ 3. insert value into stack; 4. } 5. 6. function pop( ) { 7. if(sizeof stack == 0 ){ 8. println("Stack underflow"); 9. }else { 10. delete stack[sizeof stack −1]; 11. } 12. } 13.
14. function currentStackContent(stk : Integer[] ) { 15. print(reverse stk); 16. } 17. 18. function peak() { 19. if(sizeof stack == 0 ){ 20. println("Sorry..! there are no elements in the stack."); 21. }else { 22. println(" { stack[sizeof stack −1] } is the topmost element 23. in the stack."); 24. } 25. } 26. 27. push(5); 28. push(3); 29. push(45); 30. push(25); 31. push(98); 32. println("Content of the stack"); // Content of the stack 33. currentStackContent(stack); // [ 98, 25, 45, 3, 5 ] 34. pop(); 35. peak(); // 25 is the topmost element in the stack. 36. pop(); 37. println("Content of the stack"); // Content of the stack 38. currentStackContent(stack ); // [ 45, 3, 5 ]
In Listing 10-13, the function push
inserts an element into the stack; for each call of the push
function the element is inserted at the end of the stack Integer sequence. The function pop
deletes the last element of the stack using the sizeof
operator before deleting the element, because we are checking for the availability of the element in the stack sequence. If the element is available, then the last element of the stack sequence is deleted. The function peep
is used to check the last element of the stack sequence. The final and most interesting function is currentStackContent.
It is used to display the elements of the stack sequence in reverse order (elements are printed in reverse order to achieve the last-in, first-out concept of stack implementation), where the sequence is sent as the parameter of the function, so that stack sequence is not modified.
Functions can also return a sequence as a return value. Let's modify the curentStackContent
function so that it can return the reversed sequence.
function currentStackContent(stk : Integer[] ) : Integer[] { return reverse stk; }
Function calls to currentStackContent
should be modified accordingly.
Unlike binding a variable, it is common to bind a sequence in JavaFX Script. When a variable is bound to an individual element of a sequence, any change either to the value of the element or its position (for example, when an element is inserted or deleted) is reflected in the bound variable.
The example in Listing 10-14 demonstrates how an element of a sequence is bound to a variable.
Example 10.14. Binding an element of a sequence to a variable
1. var seq = [10, 20, 30]; 2. var z = bind seq[1]; // z is bound to seq[1] 3. println(seq); // [ 10,20,30 ] 4. println("z={ z }"); // z=20 5. insert 55 before seq[1]; 6. println(seq); // [10,55,20,30 ] 7. println(" z={ z }"); // z=55 8. seq[1] = 38; 9. println(seq); //[10,38,20,30] 10. println(" z={ z }"); //z=38 11. delete seq[1]; 12. println(seq); // [10,20,30] 13. println(" z={ z }"); // z=20
In line 2, the variable z
is bound to the second element of the seq
sequence, seq[1]
. When a new element is inserted at the second position of seq
as in line 5 , the z
value changes, reflecting the insertion of a new element at position seq[1]
. The z
value changes even when the element is updated, as in line 8.
You know that a sequence can be created using a range expression; we can also bind
the sequence values to the range expression, Any changes that apply to the range expression directly will reflect the values of the sequence.
Listing 10-15 demonstrates how sequence values are bound to the range expression.
Example 10.15. Binding the sequence values to the range expression
1. var num = 5; 2. var seq1 : Integer[] = bind [1..num]; 3. println(seq1); // [ 1,2,3,4,5 ] 4. num = 10; 5. println(seq1); // [ 1,2,3,4,5,6,7,8,9,10 ] 6. num = 6; 7. println(seq1); // [ 1,2,3,4,5,6 ]
Here, the seq1
is bound to the range expression, which goes from 1 to the value of num
. As the value of num
changes, the seq1
sequence values also change, as in lines 1, 4, and 6.
Just as binding can be applied between two variables, it can also be applied between two sequences. Any changes that occur to the source sequence, whether by inserting a new element, deleting an element, or any other change to the existing elements in the sequence, are reflected by changes in the destination sequence. In fact, even bidirectional binding can be applied between sequences, as demonstrated by the example in Listing 10-16.
Example 10.16. Binding applied between two sequences
1. var seq1 = [1..5]; 2. println(seq1); // [ 1, 2, 3, 4, 5 ] 3. var seq2 = bind seq1 with inverse; 4. println(seq2); // [ 1, 2, 3, 4, 5 ] 5. insert 100 before seq1[3]; 6. println(seq1); // [ 1, 2, 3, 100, 4, 5 ] 7. println(seq2); // [ 1, 2, 3, 100, 4, 5 ] 8. insert 555 into seq2; 9. println(seq1); // [ 1, 2, 3, 100, 4, 5, 555 ] 10. println(seq2); // [ 1, 2, 3, 100, 4, 5, 555 ] 11. delete 5 from seq1; 12. println(seq1); // [ 1, 2, 3, 100, 4, 555 ] 13. println(seq2); // [ 1, 2, 3, 100, 4, 555 ]
The javafx.util.Sequences
class in JavaFX Script contains various functions for manipulating sequences. All the functions in this javafx.util.Sequences
class are nonmutative; that is, they do not change the input parameters, but create new instances for output.
Following are the functions of the Javafx.util.Sequences class; you can see their descriptions in the API documentation:
sort(
seq
)
sort(
seq
,comparator
)
binarySearch(
seq
, key
);
binarySearch(
seq
,key
,comparator
)
indexByIdentity(
seq
,key
)
indexOf(
seq
,key
)
isEqualByContentIdentity(
seq1
, Seq2
)
max(
seq
)
max(
seq
, comparator
)
min(
seq
)
min(
seq
,comparator
)
nextIndexByIdentity(
seq
,key
,pos
)
nextIndexOf(
seq
,key
,pos
)
reverse(
seq
)
shuffle(
seq
)
A sequence is an ordered list of items of the same type. In that respect sequences are like arrays in Java, but with the difference that in Java arrays are objects and in JavaFX Script sequences are not. Elements of a sequence always start from the zeroth index and end at sizeof
the sequence minus 1. Elements of the sequence can be defined explicitly in the declaration statement by enclosing them within square brackets ([ ] ), or they can be inserted into the sequence dynamically using the insert
keyword with the before
and after
keywords to specify a desired position. Likewise, elements of a sequence can be deleted using the delete
keyword. Range expressions can be used to create a sequence. Sequence slicing provides access to portions (subsets) of a sequence. Predicates are Boolean expressions used to create a new sequence that is a subset of an existing sequence. A sequence can be reversed using the reverse
keyword. Either a single element of the sequence or the whole sequence can be bound to a variable or to a sequence. Finally, the Javafx.util.Sequence
class contains various functions for manipulating sequences.