package com.mindprod.example;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import static java.lang.System.*;
/**
* Demonstrate five ways to dedup a collection.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.1 2016-08-05 add preserveOrder, more accurating timing.
* @since 2016-05-02
*/
public class DeDup
{
private static ArrayList<String> a = new ArrayList<>( 10 );
/**
* sort and scan the array bottom to top
*
* @param a
*/
private static void bottomToTop( final ArrayList<String> a )
{
final int n = a.size();
if ( n < 2 )
{
return;
}
Collections.sort( a );
String prev = a.get( n - 1 );
for ( int i = n - 2; i >= 0; i-- )
{
final String here = a.get( i );
if ( here.equals( prev ) )
{
a.remove( i );
}
else
{
prev = here;
}
}
}
/**
* sort and copy to a new Collection
*
* @param a
*/
private static void copy( final ArrayList<String> a )
{
final int n = a.size();
if ( n < 2 )
{
return;
}
Collections.sort( a );
ArrayList<String> b = new ArrayList<>( n );
String prev = null;
for ( String here : a )
{
if ( !here.equals( prev ) )
{
b.add( here );
prev = here;
}
}
a.clear();
a.addAll( b );
}
/**
* display contents of the ArrayList
*/
private static void display()
{
a.forEach( out::println );
out.println( "----------------" );
}
/**
* load the ArrayList up with some sample data
*/
private static void init()
{
a.clear();
a.add( "giraffe" );
a.add( "giraffe" );
a.add( "giraffe" );
a.add( "lion" );
a.add( "tiger" );
a.add( "penguin" );
a.add( "elephant" );
a.add( "PENGUIN" );
a.add( "tiger" );
a.add( "ibex" );
}
/**
* Remove duplicates if match equalIgnoreCase
* Preserve original order.
*
* @param a
*/
private static void preserveOrder( final ArrayList<String> a )
{
outer:
for ( int i = a.size() - 1; i >= 1; i-- )
{
for ( int j = 0; j < i; j++ )
{
if ( a.get( j ).equalsIgnoreCase( a.get( i ) ) )
{
a.remove( i );
continue outer;
}
}
}
}
/**
* use a HashSet
*
* @param a
*/
private static void withHashSet( final ArrayList<String> a )
{
HashSet<String> h = new HashSet<>( a.size() * 2 );
for ( String elt : a )
{
h.add( elt );
}
a.clear();
a.addAll( h );
}
/**
* sort and use an Iterator
*
* @param a
*/
private static void withIterator( final ArrayList<String> a )
{
if ( a.size() < 2 )
{
return;
}
Collections.sort( a );
String prev = null;
for ( Iterator<String> iter = a.iterator(); iter.hasNext(); )
{
String here = iter.next();
if ( here.equals( prev ) )
{
iter.remove();
}
else
{
prev = here;
}
}
}
/**
* sort and scan the array top to bottom , fails with IndexOutOfBoundsException
*
* @param a
*/
private static void wontWork( final ArrayList<String> a )
{
try
{
final int n = a.size();
if ( n < 2 )
{
return;
}
Collections.sort( a );
String prev = a.get( 0 );
for ( int i = 1; i < n; i++ )
{
final String here = a.get( i );
if ( here.equals( prev ) )
{
a.remove( i );
}
else
{
prev = here;
}
}
}
catch ( IndexOutOfBoundsException e )
{
out.println( "fail" );
}
}
public static void main( String[] args )
{
init();
out.println( "UNPROCESSED" );
display();
long start;
out.println( "BOTTOM TO TOP" );
start = System.nanoTime();
bottomToTop( a );
out.println( System.nanoTime() - start + " ns" );
display();
out.println( "ITERATOR" );
init();
start = System.nanoTime();
withIterator( a );
out.println( System.nanoTime() - start + " ns" );
display();
out.println( "PRESERVE_ORDER" );
init();
start = System.nanoTime();
preserveOrder( a );
out.println( System.nanoTime() - start + " ns" );
out.println( "HASHSET" );
init();
start = System.nanoTime();
withHashSet( a );
out.println( System.nanoTime() - start + " ns" );
display();
out.println( "COPY TO A NEW COLLECTION" );
init();
start = System.nanoTime();
copy( a );
out.println( System.nanoTime() - start + " ns" );
display();
out.println( "TOP TO BOTTOM : WON'T WORK" );
init();
start = System.nanoTime();
wontWork( a );
out.println( System.nanoTime() - start + " ns" );
display();
}
}