Showing posts with label guava. Show all posts
Showing posts with label guava. Show all posts

Saturday, September 28, 2013

Guava 15 - New features

A new version of the Guava library was released earlier this month and contains several new features and improvements.

Here is an overview of some of the significant API additions in this release:

1. Escapers
Escapers allow you to "escape" special characters in a string in order to make the string conform to a particular format. For example, in XML, the < character must be converted into &lt; for inclusion in XML elements. Guava provides the following Escapers:

You can also build your own Escaper. Here is an example of various Escapers in action:
// escaping HTML
HtmlEscapers.htmlEscaper().escape("echo foo > file &");
// [result] echo foo &gt; file &amp;

// escaping XML attributes and content
XmlEscapers.xmlAttributeEscaper().escape("foo \"bar\"");
// [result] foo &quot;bar&quot;

XmlEscapers.xmlContentEscaper().escape("foo \"bar\"");
// [result] foo "bar"

// Custom Escaper
// escape single quote with another single quote
// and escape ampersand with backslash
Escaper myEscaper = Escapers.builder()
                            .addEscape('\'', "''")
                            .addEscape('&', "\&")
                            .build();

2. StandardSystemProperty
StandardSystemProperty is an enum of Java system properties such as java.version, java.home etc. The great thing about this is that you no longer need to remember what the system properties are called because you simply use the enum! Here is an example:

StandardSystemProperty.JAVA_VERSION.value();
// [result] 1.7.0_25

StandardSystemProperty.JAVA_VERSION.key();
// [result] java.version

3. EvictingQueue
The EvictingQueue is a non-blocking queue which removes elements from the head of the queue when it is full and you attempt to insert a new element. Example:

// create an EvictingQueue with a size of 3
EvictingQueue<String> q = EvictingQueue.create(3);
q.add("one");
q.add("two");
q.add("three");
q.add("four");
// the head of the queue is evicted after adding the fourth element
// queue contains: [two, three, four]

4. fileTreeTraverser
As its name suggests, Files.fileTreeTraverser allows you to traverse a file tree.

FluentIterable<File> iterable = Files.fileTreeTraverser().breadthFirstTraversal(new File("/var/tmp"));
for (File f : iterable) {
    System.out.println(f.getAbsolutePath());
}

(Note: Java 7's Files.walkFileTree also traverses a file tree and I showed you to use it in one of my earlier posts: Java 7: Deleting a Directory by Walking the File Tree. I'd recommend this approach if you are using Java 7.)

The full release notes of Guava 15 can be found here.

Sunday, May 26, 2013

Guava Joiner: Converting an Iterable into a String

Guava's Joiner makes it really easy to convert an Iterable into a String, so you no longer have to iterate over it and build the String manually. Here is an example:
// joining a list
final List<String> fruits = Lists.newArrayList("apple", "banana", null, "cherry");
System.out.println(Joiner.on(", ").skipNulls().join(fruits));

// joining a map
final Map<String, Integer> people = ImmutableMap.of("Alice", 21, "Bob", 19);
System.out.println(Joiner.on("\n").withKeyValueSeparator(": ").join(people));
prints:
apple, banana, cherry
Alice: 21
Bob: 19

Saturday, February 02, 2013

Guava Table

Guava's Table<R, C, V> is a useful alternative to nested maps of the form Map<R, Map<C, V>>. For example, if you want to store a collection of Person objects keyed on both firstName and lastName, instead of using something like a Map<FirstName, Map<LastName, Person>>, it is easier to use a Table<FirstName, LastName, Person>.

Here is an example:

final Table<String, String, Person> table = HashBasedTable.create();
table.put("Alice", "Smith", new Person("Alice", "Smith"));
table.put("Bob", "Smith", new Person("Bob", "Smith"));
table.put("Charlie", "Jones", new Person("Charlie", "Jones"));
table.put("Bob", "Jones", new Person("Bob", "Jones"));

// get all persons with a surname of Smith
final Collection<Person> smiths = table.column("Smith").values();

// get all persons with a firstName of Bob
final Collection<Person> bobs = table.row("Bob").values();

// get a specific person
final Person alice = table.get("Alice", "Smith");

Saturday, December 24, 2011

Guava Cache

Google's Guava Cache is a lightweight, threadsafe Java cache that provides some nice features such as:
  • eviction of least recently used entries when a maximum size is breached
  • eviction of entries based on time since last access or last write
  • notification of evicted entries
  • performance statistics e.g. hit and miss counts
In order to create the Cache, you need to use a CacheBuilder. This allows you to specify the eviction policy and other features such as concurrency level, soft or weak values etc. You also need to specify a CacheLoader which will be invoked automatically by the cache if a key does not exist and is used to populate it.

The following code demonstrates how to create a cache:

// Create the cache. Only allow a max of 10 entries.
// Old entries will be evicted.
final Cache<String, String> cache = CacheBuilder.newBuilder()
    .maximumSize(10)
    .removalListener(new RemovalListener<String, String>() {
        @Override
        public void onRemoval(RemovalNotification<String, String> n) {
            System.out.println("REMOVED: " + n);
        }
    })
    .build(new CacheLoader<String, String>() {
        @Override
        public String load(String key) throws Exception {
            System.out.println("LOADING: " + key);
            return key + "-VALUE";
        }
    });

// Get values from the cache.
// If a key does not exist, it will be loaded.
for (int i = 0; i < 10; i++) {
  System.out.println(cache.get("Key" + i));
}
for (int i = 9; i >= 0; i--) {
  System.out.println(cache.get("Key" + i));
}

//Print out the hit counts.
System.out.println(cache.stats());
The output of this program is:
LOADING: Key0
LOADING: Key1
LOADING: Key2
LOADING: Key3
LOADING: Key4
LOADING: Key5
LOADING: Key6
REMOVED: Key0=Key0-VALUE
LOADING: Key7
REMOVED: Key3=Key3-VALUE
LOADING: Key8
LOADING: Key9
LOADING: Key3
REMOVED: Key7=Key7-VALUE
LOADING: Key0
REMOVED: Key6=Key6-VALUE
CacheStats{hitCount=8, missCount=12, loadSuccessCount=12, loadExceptionCount=0, 
totalLoadTime=563806, evictionCount=4}
It is important to note that entries were evicted BEFORE the maximum size of 10 was reached. In this case, an entry was removed when the cache had 7 entries in it.

The cache stats show that out of 20 calls to the cache, 12 missed and had to be loaded. However, 8 were successfully retrieved from the cache. 4 entries were evicted.