Showing posts with label Guava. Show all posts
Showing posts with label Guava. Show all posts

Java Frequently Used Utillity Methods


Objects.requireNonNull(key, message)
Objects.equals(a,b) - null safe
StringBuilder
.charAt(i) 
.setCharAt(int, char)
.setLength(0)/setLength(len-1)
- O(1) if decrease the length
.reverse()
.insert(offset,value)
.delete(start,end)
.deleteCharAt(i)


Arrays.equals(a1,a2)
.fill(long[] a, long val)
fill(long[] a, int fromIndex, int toIndex, long val)

To fill multiple dimension arrays:
int[][] target = new int[2][4];
int [] temp = new int[4];
Arrays.fill(temp, -1);

Arrays.fill(target, temp);

Collection
List
E remove(int index);
boolean remove(Object o);

ListIterator
next/hasNext/nextIndex, previous/hasPrevious/previousIndex, 
add/remove/set

ArrayList.subList
remove elements from startIndex to endIndex
list1.subList(startIndex, endIndex).clear();
Don't update original list while still need the subList.

Arrays.asList(T…a) returns a Subclass of AbstractList that doesn’t implement the add or remove method - it throws UnsupportedOperationException.

JDK 8
map.putIfAbsent(sum, i);
Instead of:
if (!map.containsKey(sum)) {
    map.put(sum, i);
}

map.getOrDefault(key, defaultValue)
computeIfAbsent
computeIfPresent

Lambda
iterable.forEach(x -> x.setXXX(null));
list.removeIf(s -> s.length() == 0);

Stream
list.replaceAll(s -> s.toUpperCase());
list.sort((x, y) -> x.length() – y.length());
logger.finest(() -> complexMsg());
lineCount = Files.lines(path).count();

Collectors
stream().collect(Collectors.groupingBy(xxx));
mapStream.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

Math:
Math.xxxExact - throws exception if overflow
addExact/subtractExact...
Base64

SecureRandom.getInstanceStrong()

Enum
SomeEnum someEnum = Enum.valueOf(SomeEnum.class, value);

// Need escape ': ''
MessageFormat.format

Initilaize 2-d array
int[][] target = new int[2][4];
int [] temp = new int[4];
Arrays.fill(temp, -1);
Arrays.fill(target, temp);

Get the inputstream from classpath:
ClassLoader.getResourceAsStream()

Guava
Preconditions
MoreObjects
firstNonNull(@Nullable T first, @Nullable T second)
joiner = Joiner.on("; ").skipNulls();
splitter = Splitter.on(',').trimResults().omitEmptyStrings();

ComparisonChain.start().compare(this.aString, that.aString)....compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast()).result();

Ordering<String> ordering = = Ordering.nullsFirst().reverse();

Collections.sort(names, ordering);
Map<String, String> paramMap = Splitter.on("&").withKeyValueSeparator("=").split(params);
Joiner.on("&").withKeyValueSeparator("=").join(paramMap);

CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName);

HtmlEscapers.htmlEscaper().escape(str)
UrlEscapers.urlFormParameterEscaper()/urlFragmentEscaper()/urlPathSegmentEscaper()/urlFormParameterEscaper().

Files.hash(file, Hashing.md5());
RateLimiter

Solr Commons
DateUtil.parseDate(dateString)
DateUtil.getThreadLocalDateFormat().format(date)

Top 16 Java Utility Classes
Apache Commons
StringUtils
CollectionUtils
ReflectionToStringBuilder.toString(this)

org.apache.commons.lang.SerializationUtils
clone
serialize
deserialize

ObjectUtils
firstNonNull(T... values)
defaultIfNull(final T object, final T defaultValue)

ArrayUtils.contains(arr,targetValue)


Java Collection: Using Collections API


Common Collections Utils
Collections.sort(), max(), min(), .reverse(), shuffle(),rotate()
Collections.swap(),fill(), copy(),replaceAll(),
return Collections.emptyList(), unmodifiabkeList(), synchronizedList(),checkedList()

Collections.disjoint(c1,c2) -- return number of common elements
Collections.frequency(c, obj) -- how many times the element appears. 
Collections.nCopies(n, T) -- better performance

Collections.reverseOrder() -- returns a comparator that do reverse of that natural ordering
Collections.reverseOrder(Comparator cmp)
Use ListIterator
 ArrayList<Integer> arr = new ArrayList<Integer>();
  ListIterator<Integer> listIt = arr.listIterator();
 while(listIt.hasPrevious())
 {
  Integer i = listIt.previous();
  int idx = listIt.previousIndex();
 }
 
 LinkedList<Integer> list = new LinkedList<>();
 listIt = list.listIterator();
 
 // or use descendingIterator
 Iterator<Integer> descIt = list.descendingIterator();

Collections.rotate - left rotate
 LinkedList<Integer> list = Arrays.asList(0,1,2,3,4);
 LinkedList<Integer> newList = new LinkedList<>(list);
 Collections.rotate(newList, 1);
 System.out.println(newList); // [4, 0, 1, 2, 3]
 newList = new LinkedList<>(list);
 //Collections.rotate(newList, -1);/[1, 2, 3, 4, 0]
 System.out.println(newList);

Collections.binarySearch
If there are multiple elements equal to the specified object in the sorted list, there is no guarantee which one will be found. If we want to always return the first or last element, write our own binarySearch implementation.

Union of two Collections:
list1.addAll(list2)

Intersection of two Collections:
list1.retainAll(list2)

Difference between two Collections
list1.removeAll(list2)

Collections.API Usage
List<Integer> list = Collections.nCopies(10, -1);
// this will throws java.lang.UnsupportedOperationException
// list.add(-11);

list = new ArrayList<>(Collections.nCopies(10, -1));
list.add(-11);

// list is still 0 length
Collections.fill(list, -1);

// add them to the list
Collections.addAll(list, 1, 1, 1, 1, 1);
Caveat: Can't add or remove element into the list returned by Arrays.asList
The return type is private static inner class: java.util.Arrays.ArrayListWe can iterate, get or change(set) existing elment, but can't not add or remove elements, which will throw UnsupportedOperationException.

Caveat: Don't use primitive array as parameter of Arrays.asList
It actually puts the whole primitive array as the first element in the result list. From the following example, the result list type is List<int[]> not List<Integer> .
List<int[]> list = Arrays.asList(new int[] { 0, 1, 2, 3, 4 }); 
System.out.println(list); //[[I@45ff54e6]
System.out.println(list.size()); //1
System.out.println(list.get(0).getClass()); //class [I
System.out.println(list.get(0));//[I@45ff54e6

Using Guava Ints.asList to convert int[] to List
When we want to convert primitive array to it's List of wrapper type, and don't want to write the loop, we can use Guava's primitive utils: Ints, Longs, Doubles and etc.
int maxValue = Collections.max(Ints.asList(intArray));

Equality for Collection
Collection determines equality by content: They are same as long as two lists belong to same interface(List, Set) and have same elements.
List<Integer> arr = new ArrayList<>();
arr.add(1);
List<Integer> list = new LinkedList<>();
list.add(1);
assertTrue(arr.equals(list));

Set<Integer> hashSet = new HashSet<>();
hashSet.add(1);

Set<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
assertTrue(hashSet.equals(treeSet));

Performance
Using LinkedList when add or remove elements frequently

In Single thread application, when iterate ArrayList in performance-critical section, consider using for-get to loop elements in stead of using for-loop or iterator> This can avoid the unnecessary concurrent modification check.

Using Guava to Convert between Primitives Array and Wrapper List


Usually we nee convert between primitives array to wrapper list, for example: convert int[] to List.
Solution 1: Convert them manully
We can write code to convert them manually like below:
 public void intArrayIntListManully() {
    int[] aInts = {1, 2, 3};
    // int array to List
    List aList = new ArrayList(aInts.length);
    for (int i : aInts) {
      aList.add(i);
    }
    System.out.println(aList);
    // this throws UnsupportedOperationException
    // aList.add(4);
    // aList.remove(0);

    // List to int array
    aInts = new int[aList.size()];
    for (int i = 0; i < aList.size(); i++) {
      aInts[i] = aList.get(i);
    }
    System.out.println(aInts.length);
  }
But it's kind of annoy to have to write this boilerplate code  again and again.
Solution 2: Using Guava primitives
We can use utils in Guava com.google.common.primitives to easily convert between them: the code is cleaner, also its performance is better.

public void intArrayIntListViaGuava() {
  int[] aInts = {1, 2, 3};
  List<Integer> aList = Ints.asList(aInts);
  System.out.println(aList);
  
  aInts = Ints.toArray(aList);
  System.out.println(aInts.length);
}
If we check Guava's implementation, Ints.asList doesn't create one ArrayList then add all ints to that list, instead, it creates IntArrayAsList which holds a reference to the original int array, its get method creates and returns the wrapper object.
We can't add new element or remove element to the IntArrayAsList.
  public static List<Integer> asList(int[] backingArray)
  {
    if (backingArray.length == 0) {
      return Collections.emptyList();
    }
    return new IntArrayAsList(backingArray);
  }
  
  public static int[] toArray(Collection<? extends Number> collection)
  {
    if (collection instanceof IntArrayAsList) {
      return ((IntArrayAsList)collection).toIntArray();
    }

    Object[] boxedArray = collection.toArray();
    int len = boxedArray.length;
    int[] array = new int[len];
    for (int i = 0; i < len; ++i)
    {
      array[i] = ((Number)Preconditions.checkNotNull(boxedArray[i])).intValue();
    }
    return array;
  }
 private static class IntArrayAsList extends AbstractList<Integer>    implements RandomAccess, Serializable
  {
    final int[] array;
    final int start;
    final int end;
    IntArrayAsList(int[] array)
    {
      this(array, 0, array.length);
    }

    IntArrayAsList(int[] array, int start, int end) {
      this.array = array;
      this.start = start;
      this.end = end;
    }
    public Integer get(int index) {
      Preconditions.checkElementIndex(index, size());
      return Integer.valueOf(this.array[(this.start + index)]);
    } 
  }
Solution 3: Using Apache Commons Lang
If your project doesn't use Guava, you may use Apache Commons Lang:
public void intArrayIntListViaCommonsLang() {
  int[] aInts = {1, 2, 3};
  List<Integer> aList = Arrays.asList(ArrayUtils.toObject(aInts));
  System.out.println(aList);
  
  aInts = ArrayUtils.toPrimitive(aList.toArray(new Integer[aList.size()]));
  System.out.println(aInts.length);
}
Reference
Guava Primitives Explained

Collections in Guava


Google Guava is an open source library which provides lots of useful utility to Java programmer,  one of them is easy way to find the difference between two maps.
MapDifference of two Maps

public void getMapDiff() {
    Map<Integer,Integer> leftMap = ImmutableMap.of(1, 1, 2, 2, 4, 40);
    Map<Integer,Integer> rightMap = ImmutableMap.<Integer,Integer> builder()
        .put(2, 2).put(3, 3).put(4, 41).build();
    MapDifference<Integer,Integer> diff = Maps.difference(leftMap, rightMap);
    
    // output: entriesInCommon:{2=2}
    System.out.println("entriesInCommon:" + diff.entriesInCommon());
    // output: entriesOnlyOnLeft:{1=1}
    System.out.println("entriesOnlyOnLeft:" + diff.entriesOnlyOnLeft());
    // output: entriesOnlyOnRight:{3=3}
    System.out.println("entriesOnlyOnRight:" + diff.entriesOnlyOnRight());
    
    Map<Integer,ValueDifference<Integer>> entriesDiffering = diff
        .entriesDiffering();
    // output: entriesDiffering: {4=(40, 41)}
    System.out.println("entriesDiffering: " + entriesDiffering);
  }

Simple Cache Implementation in Java


LRU Cache: Using LinkedHashMap
Java LinkedHashMap and LinkedHashSet maintains the order of insertion or access. By default it's the insertion order, we can change it using the constructor: LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder).
Setting accessOrder to true would make LinkedHashMap sort elements according to the order of access.

LinkedHashMap maintains an extra doubled linked list to maintain the element order: Entry<K,V> header; The header is like a sentinel element, its after points to the oldest element.

LinkedHashMap.removeEldestEntry(Map.Entry<K,V> eldest) allow us to specify whether to remove the oldest one.
class LRUCacheMap<K, V> extends LinkedHashMap<K, V> {
  private static final long serialVersionUID = 1L;
  private int capacity;
  public LRUCacheMap(int capacity) {
    this.capacity = capacity;
  }
  @Override
  protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
    return size() > capacity;
  }
}

LRU Cache: Using LinkedHashSet
1. Overwrite add method in LinkedHashSet
When implement a hash based LRU cache, we can extend LinkedHashSet, then overwrite its add method: when current size is equal or larger than MAX_SIZE, use the iterator to remove the first element, than add the new item.
class LRUCacheSet<E> extends LinkedHashSet<E> {
  private static final long serialVersionUID = 1L;
  private int capacity;
  public LRUCacheSet(int capacity) {
    this.capacity = capacity;
  }
  @Override
  public boolean add(E e) {
    if (size() >= capacity) {
      // here, we can do anything.
      // 1. LRU cache, delete the eldest one(the first one) then add the new
      // item.
      Iterator<E> it = this.iterator();
      it.next();
      it.remove();

      // 2. We can do nothing, just return false: this will discard the new
      // item.
      // return false;
    }
    return super.add(e);
  }
}
2. Using LinkedHashMap to implement LRUCacheSet via Collections.newSetFromMap
HashSet actually uses a HashMap as the backend. Collections.newSetFromMap (introduced in JDK6) allow us to construct a set backed by the specified map. The resulting set displays the same ordering, concurrency, and performance characteristics as the backing map.

So we can use the previous LRUCacheMap as the backing map.
lruCache = Collections.newSetFromMap(new LRUCacheMap<Integer, Boolean>(
    MAX_SIZE));
for (int i = 0; i < 10; i++) {
  lruCache.add(i);
}
Assert.assertArrayEquals(new Integer[] { 5, 6, 7, 8, 9 },
      lruCache.toArray());

More about Collections.newSetFromMap
There are many HashMap implementations that doesn't have a corresponding Set implementation: such as ConcurrentHashMap, WeakHashMap, IdentityHashMap. 
Now we can easily create hash instances that work same as ConcurrentHashMap,ConcurrentSkipListMap, WeakHashMap:
Set<Object> concurrenthashset = Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>());
Set<Object> weakHashSet = Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());

Using Guava CacheBuilder
Google Guava is a very useful library, and it's most likely that it's already included in our project. Guava provides a CacheBuilder which allows us to build a custom cache with different features combination.
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000).expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
 new CacheLoader<Key, Graph>() {
   public Graph load(Key key) throws AnyException {
     return createExpensiveGraph(key);
   }
});
Resources
LinkedHashMap's hidden (?) features
Handy But Hidden: Collections.newSetFromMap()
Guava CacheBuilder

Using Guava Splitter and Joiner


In my last post: Solr RssResponseWriter by Extending XMLWriter, I need parse the field mapping string like: topic:title,url:link,description:description to a map.

If we have to write our own code, the code would look like below:
public void splitOnOurOwn() {
 String mapStr = "topic: title, url: link, description: description ";
 String[] pairs = mapStr.split(",");
 Map<String,String> map = new HashMap<String,String>();
 for (String pair : pairs) {
  String[] str = pair.split(":");
  map.put(str[0].trim(), str[1].trim());
 }
 System.out.println("toString: " + Objects.toString(map));
}
But if we use Guava it would be just two lines:

private static MapSplitter splitter = Splitter.on(",").trimResults()
  .withKeyValueSeparator(Splitter.on(':').trimResults());
private static MapJoiner joinner = Joiner.on(",").withKeyValueSeparator(":");

public void guavaSplit() {
 String mapStr = "topic: title, url: link, description: description ";
 Map<String,String> map = splitter.split(mapStr.trim());
 System.out.println("toString: " + Objects.toString(map));
 System.out.println("join: " + joinner.join(map));
}
Guava Splitter provides some other useful methods such as fixedLength, omitEmptyStrings, trimResults, limit.


As described in code above, Guava provides a Joiner that can join text with a separator. Joiner also provides useful methods such as skipNulls, useForNull(nullText).
Resources
Strings Explained
Splitter Javadoc
Joiner Javadoc
Guava Splitter vs StringUtils

Using Guava Stopwatch


When read this post, TRIM, LTRIM and RTRIM in Java

I have a doubt about the performance difference between the one uses regular expression ltrim and the straightforward ltrim3. So I use Guava topwatch
to test their performance. 
Guava Usage
1. Use Stopwatch static factory method to create one instance.
Stopwatch stopwatch = Stopwatch.createStarted()
2. Use stopwatch.elapsed(TimeUnit) to get elapsed time.
3. We can reuse same stopwatch instance to measures another operation, but we have to first call reset(), and start().
reset() method would reset internal variable: elapsedNanos=0, isRunning=false. Calling start() would start again to measure time elapsed.
Conclusion
The test result is as what I expected, the straightforward one gives the best performance.
458 for ltrim3(the straightforward one)
3967 for ltrim(using regular expression)

The code looks like below:
import com.google.common.base.Stopwatch;

public class LTrimTester {
  private final static Pattern LTRIM = Pattern.compile("^\\s+");
  private final static Pattern RTRIM = Pattern.compile("\\s+$");

  public static void main(String[] args) {
    int times = 10000000;
    Stopwatch stopwatch = Stopwatch.createStarted();
    for (int i = 0; i < times; i++) {
      String str = "  hello world  ";
      ltrim(str);
    }
    System.out.println(stopwatch.elapsed(TimeUnit.MILLISECONDS)
        + " for ltrim(using regular expression)");

    stopwatch.reset();
    stopwatch.start();
    for (int i = 0; i < times; i++) {
      String str = "  hello world  ";
      ltrim3(str);
    }
    System.out.println(stopwatch.elapsed(TimeUnit.MILLISECONDS)
        + " for ltrim3(the straightforward one)");
    stopwatch.stop();
  }

  public static String ltrim(String s) {
    return LTRIM.matcher(s).replaceAll("");
  }

  public static String ltrim3(String s) {
    int i = 0;
    while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
      i++;
    }
    return s.substring(i);
  }
}
Resources
TRIM, LTRIM and RTRIM in Java
Guava Stopwatch Javadoc
Guava Stopwatch

Labels

ANT (6) Algorithm (69) Algorithm Series (35) Android (7) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) JSON (7) Java (186) JavaScript (27) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) adsense (5) bat (8) regex (5) xml (5)