Posted by

swchan2 on July 1, 2013 at 3:51 PM PDT

Expression Language (EL) was first introduced as part of JSTL 1.0, was then moved JSP 2.0 and was unified with JSF 1.2 in JSP 2.1. In Java EE 7, EL is a new separate JSR, JSR 341 . Many new features are introduced in EL 3.0.

This blog shows how to use new following new features of EL 3.0:

- Standalone environment
- Lambda expression (section 1.20 of EL 3.0 spec)
- The new operator
`;`

to separate statements
- Retrieval of a
`Stream`

from a `Collection`

(section 2.3.1 of EL 3.0 spec)
- The use of a static field and method, for instance,
`Math.sqrt`

This blog also shows how to use new operations to calculate a standard deviation in the following different ways:

- Using
`count`

, `sum`

and `map`

- Using
`forEach`

- Using
`reduce`

(see section 2.3.17 of EL 3.0 spec)

I would like to thank Kinman Chung, the EL specification lead, for useful discussion.

The following example shows some of the new EL features.

`public class ELTestServlet extends HttpServlet {`

@Override

public void doGet(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException {

List list = new ArrayList<>();

list.add(Double.valueOf(1.0));

list.add(Double.valueOf(2.0));

list.add(Double.valueOf(3.0));

ELProcessor elp = new ELProcessor();

elp.defineBean("data", list);

Object message = (Double)elp.eval(

"n = data.stream().count(); s = data.stream().sum(); sq = data.stream().map(i -> i*i).sum(); Math.sqrt(sq/n - Math.pow(s/n, 2))");

res.getWriter().println(message);

message = (Double)elp.eval(

"n = 0; s = 0; sq = 0; data.stream().forEach(d -> (n = n + 1; s = s + d; sq = sq + d*d)); Math.sqrt(sq/n - Math.pow(s/n, 2))");

res.getWriter().println(message);

message = (Double)elp.eval(

"n = 0; s = 0; sq = data.stream().reduce(0, (a, i) -> (n = n + 1; s = s + i; a + i*i)); Math.sqrt(sq/n - Math.pow(s/n, 2))");

res.getWriter().println(message);

}

}

We will use EL in a servlet as a *standalone environment*. In this case, an `ELProcessor`

is created and beans are defined as follows:

` ELProcessor elp = new ELProcessor();`

elp.defineBean("data", list);

An EL can be evaluated by using `elp.eval(...)`

.

## EL Example 1: Using count, sum and map

` n = data.stream().count();`

s = data.stream().sum();

sq = data.stream().map(i -> i*i).sum();

Math.sqrt(sq/n - Math.pow(s/n, 2))

For a given collection,

`stream()`

allows access to the corresponding

`Stream`

.

Then `count()`

and `sum()`

can be called on the `Stream`

to count the number of elements and compute the sum of elements in the associated collection.

For `data.stream().map(i -> i*i)`

, a Lambda expression is used. In this case, the expression changes each value in the `Stream`

to its square.

## EL Example 2: Using forEach

` n = 0; s = 0; sq = 0;`

data.stream().forEach(d -> (n = n + 1; s = s + d; sq = sq + d*d));

Math.sqrt(sq/n - Math.pow(s/n, 2))

This EL uses

`forEach`

for a

`stream`

. The count, sum and sum of squares are computed at the same time. Note that the variables

`n`

,

`s`

and

`sq`

are defined in EL Example 1. We need to reset them to initial values in the given

`ELProcessor`

.

## EL Example 3: Using reduce

` n = 0; s = 0;`

sq = data.stream().reduce(0, (a, i) -> (n = n + 1; s = s + i; a + i*i));

Math.sqrt(sq/n - Math.pow(s/n, 2))

In this example,

`reduce`

is used to compute the count, sum and sum of squares. In the second line, the first argument of

`reduce`

is the initial value of the

`seed`

variable

`a`

. The result of the expression is assigned back to the variable

`sq`

for subsequent computation.

We can learn more about EL 3.0 by looking at the specification in JSR 341 . EL 3.0 is available at java.net and is part of GlassFish 4.0 .