Saturday, September 15, 2012

Guava Live View of collections explained

The collection returned when using filter or transform methods is so called Live View of the underlying collection. Its iterator doesn't support removing elements, only adding. The most useful thing about Live Views is that they let you work with elements that satisfy the Predicate condition only. It is handy especially when the elements are Objects and their state changes so that the object may or may not pass the condition and be part of the unfiltered View.

In the following test case you can see them in action :

  

    @Test
    public void testLiveViews() {

        /** adding 9 arrays with 0,1,2,3,4,5,6,7,8 */
        List<Integer[]> list = new ArrayList<Integer[]>(9);
        for (int i = 0; i < 9; i++) {
            list.add(new Integer[]{i});
        }

        /** filtering arrays to even values 0,2,4,6,8 */
        Collection<Integer[]> filteredList = Collections2.filter(list, new Predicate<Integer[]>() {
            public boolean apply(Integer[] input) {
                return input[0] % 2 == 0;
            }
        });
        Assert.assertEquals(9, list.size());
        Assert.assertEquals(5, filteredList.size());

        /** filtered live view reflects changes into the underlying collection */
        Assert.assertEquals((int) list.get(2)[0], 2);
        for (Integer[] s : filteredList) {
            s[0] = s[0] + 1;
        }
        Assert.assertEquals((int) list.get(2)[0], 3);

        /** elements changed so that they don't satisfy filtering condition hence size is 0 */
        Assert.assertEquals(0, filteredList.size());
        Assert.assertEquals(9, list.size());

        /** adding even value that satisfy condition to filtered list */
        filteredList.add(new Integer[]{666});
        Assert.assertEquals(1, filteredList.size());
        Assert.assertEquals(10, list.size());

        /** adding even value that satisfy condition to underlying list */
        list.add(new Integer[]{888});
        Assert.assertEquals(2, filteredList.size());
        Assert.assertEquals(11, list.size());

        /** adding odd value that doesn't satisfy condition to filtered list */
        try {
            filteredList.add(new Integer[]{667});
            Assert.fail();
        } catch (Exception e){
            Assert.assertEquals(2, filteredList.size());
        }

        /** adding odd value that doesn't satisfy condition to underlying list */
        list.add(new Integer[]{887});
        Assert.assertEquals(2, filteredList.size());
        Assert.assertEquals(12, list.size());
    }

No comments: