Software Engineer

I am a Software Engineer. I have a Bachelor (Honours) of Science in Information Technology from the University of Sunderland - Class of 2003. I have been developing software since 2001 when I was offered a role at CERN as part of their Technical Student Programme.

By 2016 I had grown really tired of the software industry and by the end of 2019 Apple killed whatever excitement I had left. I am not sure what the next 10 years will bring. What I do know is that my apettite to do work that is impactful has only grown bigger and stronger. Great people make me tick more than anything.

I am also tired.

How To Think Of... Aspects

public class AspectSets
    {
        /**
         * Create a new Set which is strong on duplicates 
         * 
         * @param <E> the type of the {@link Set}
         * @param elements the elements to create the set from
         * @return a new Set which is only keen on holding added 
         * elements more than once.
         */
        public static <E> Set<E> newSetOnDuplicates(final E[] elements)
        {
            final Aspect<E> isUnique = Aspects.uniqueAspect();
            
            /*
             * Using a set to handle multiple duplicates
             * (elements that occur more than 2 times)
             */
            return new HashSet<E>( Lists.newArrayList(elements) )
            {
                private static final long serialVersionUID = 
                                                      -8073479479226481874L;

                /**
                 * Add the element only if its a duplicate
                 */
                @Override
                public boolean add(E e) 
                {                
                    if(isDuplicate(e))
                        return super.add(e);
                    
                return false;
                }

                private boolean isDuplicate(E e) {
                return !isUnique.apply(e);
                }
            };
        }
    }

    public class Aspects
    {
        /**
         * @param <E> the type of the objects
         * @return a new Aspect on unique objects
         */
        public static <E> Aspect<E> uniqueAspect()
        {
        return new Aspect<E>()
            {
                /*
                 * Holding all unique elements
                 */
                private final Set<E> uniques = new HashSet<E>();
                
                /**
                 * @return true if element is unique
                 */
                @Override
                public boolean apply(E e) {
                return this.uniques.add(e);
                }
            };
        }
    }

    /**
     * Survival of the fittest
     */
    public class AspectSetsTest
    {
        @Test
        public void newSetOnDuplicates() throws Exception
        {
            String[] animals = {"cat", "cat", "cat", 
                                "dog", "dog", 
                                "parrot", 
                                "lion", 
                                "zebra", "zebra"};
            
            Set<String> duplicatesOnly = AspectSets.newSetOnDuplicates(animals);
            
            Assert.assertEquals(3, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra"}), 
                            duplicatesOnly);
            
            Assert.assertTrue(duplicatesOnly.add("lion"));        
            Assert.assertEquals(4, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion"}), 
                            duplicatesOnly);
            
            Assert.assertFalse(duplicatesOnly.add("monkey"));        
            Assert.assertEquals(4, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion"}), 
                            duplicatesOnly);
            
            Assert.assertTrue(duplicatesOnly.add("monkey"));
            Assert.assertEquals(5, duplicatesOnly.size());
            Assert.assertEquals(
                    Sets.newHashSet(
                            new String[] {"cat", "dog", "zebra", "lion", "monkey"}), 
                            duplicatesOnly);
        }
    }

As inspired by @sealabcore’s “Return only duplicate values from ruby array."

Instead of extending from HashSet (Disclaimer)

    public class DuplicatesOnlySet<E> extends HashSet<E>
    {
        private final Set<E> uniques = new HashSet<E>();

        public  DuplicatesOnlySet(Collection<? extends E> c) 
        {
            super(c);
        }

        @Override
        public boolean add(E e) 
        {                
            /*
             * This is getting called at the constructor 
             * thus you will get a NPE since
             * {@link #uniques} isn't initialised yet.
             */
            if(!this.uniques.add(e))
                 return super.add(e);
        
        return false;
        }
    }

and falling into the trap of a NullPointerException.

Or using composition forcing you to create delegate calls to the backing Set and making sure all necessary method calls go through your modified #add(E e) method, you can use the notion of aspects.

Note that the constructor

    public HashSet(Collection<? extends E> c)

is actually calling the #addAll(Collection<? extends E> c) method which in return calls #add(E e) thus filtering the elements on construction.

What’s cool is that the way its integrated, any method used to traverse the returned Set will give you the expected elements. (Note)

Although we haven’t effectively changed the contract of the Set (“A collection that contains no duplicate elements”), its implementation certainly differs, so make sure you document that

Disclaimer

Technically speaking we do extend from HashSet only anonymously

Source