/** * Copyright (c) 2013 Eclipse contributors and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.emf.test.core.common.util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.BitSet; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Random; import java.util.Set; import java.util.WeakHashMap; import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.common.util.InterningSet; import org.eclipse.emf.common.util.WeakInterningHashSet; import org.junit.Test; public class WeakInterningHashSetTest { @Test public void testBasic() { WeakInterningHashSet<String> set = new WeakInterningHashSet<String>(); set.add("foo"); assertTrue(set.contains("foo")); assertEquals(1, set.size()); assertEquals("[foo]", set.toString()); { Iterator<String> iterator = set.iterator(); assertEquals("foo", iterator.next()); assertFalse(iterator.hasNext()); } set.add(null); assertTrue(set.contains(null)); assertEquals(2, set.size()); set.remove(null); assertFalse(set.contains(null)); assertEquals(1, set.size()); set.clear(); assertEquals(0, set.size()); assertTrue(set.isEmpty()); assertFalse(set.iterator().hasNext()); set.add("bar"); { Iterator<String> iterator = set.iterator(); assertEquals("bar", iterator.next()); iterator.remove(); } assertEquals(0, set.size()); } @Test public void testWeakness() { WeakInterningHashSet<String> set = new WeakInterningHashSet<String>(); { String foo = new String("foo"); set.add(foo); assertTrue(set.contains("foo")); assertEquals(1, set.size()); foo = null; } System.gc(); assertFalse(set.contains("foo")); try { // If the garbage collector a chance to enqueue the stale entries. Thread.sleep(1000); } catch (InterruptedException e) { // Expected. } assertEquals(0, set.size()); } @SuppressWarnings("unused") public static void main(String[] args) throws IOException, ClassNotFoundException { Set<Integer> numbers = new HashSet<Integer>(); if (false) { int limit = Integer.MAX_VALUE; BitSet bitSet = new BitSet(limit); for (int i = 2; i < limit / 2; ++i) { if (!bitSet.get(i)) { // System.out.println(">" + i); for (int j = i + i; j < limit && j > 0; j += i) { bitSet.set(j); } } } for (int i = 1; i < limit && i > 0; i <<= 1) { System.out.print(i); System.out.print(" -> "); for (int j = i; j < limit && j > 0; ++j) { if (!bitSet.get(j)) { System.out.println(j); break; } } } System.out.print("["); for (int i = 1; i < limit && i > 0; i <<= 1) { for (int j = i; j < limit && j > 0; ++j) { if (!bitSet.get(j)) { System.out.print(j); System.out.print(", "); break; } } } System.out.println("]"); System.out.println("Largest positive integer prime:"); for (int j = limit - 1; ; --j) { if (!bitSet.get(j)) { System.out.println(j); break; } } if (true) return; } WeakInterningHashSet<String> set = new WeakInterningHashSet<String>(); set.add("abc"); set.dump(); set.add("abc"); set.dump(); set.add("xyz"); set.dump(); set.add(null); set.dump(); String result = set.intern(new String("xyz")); set.dump(); if (result != "xyz") { System.out.println("BAD"); } set.add(new String("foo")); set.dump(); System.gc(); set.size(); set.dump(); set.add(new String("foo")); set.dump(); set.remove(new String("foo")); System.gc(); set.size(); set.dump(); set.add(new String("bar")); set.remove(new String("bar")); System.gc(); set.size(); set.dump(); set.remove(null); set.dump(); { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); objectOutputStream.writeObject(set); objectOutputStream.close(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); @SuppressWarnings("unchecked") WeakInterningHashSet<String> clone = (WeakInterningHashSet<String>)new ObjectInputStream(in).readObject(); clone.dump(); } { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); objectOutputStream.writeObject(ECollections.synchronizedInterningSet(set)); objectOutputStream.close(); ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); @SuppressWarnings("unchecked") InterningSet<String> clone = (InterningSet<String>)new ObjectInputStream(in).readObject(); System.out.println(clone); } WeakInterningHashSet<Integer> integers = new WeakInterningHashSet<Integer>(); integers.add(null); Set<Integer> stash = new HashSet<Integer>(); int count = 1000; Random random = new Random(100); for (int i = 0; i < count; ++i) { Integer integer = new Integer(random.nextInt() % (count / 4)); stash.add(integer); if (random.nextBoolean()) { integers.intern(integer); } else { integers.remove(integer); } } System.out.println("################"); integers.dump(); System.out.println("################"); stash.clear(); System.gc(); integers.size(); integers.dump(); System.out.println("################"); integers.dump(); System.out.println("################" + integers); System.gc(); System.out.println("################" + integers); count = 100000; WeakInterningHashSet<String> strings = new WeakInterningHashSet<String>(); Set<String> stringStash = new HashSet<String>(); for (int i = 0; i < count; ++i) { StringBuilder builder = new StringBuilder(); for (int j = 0, size = (random.nextInt() >>> 1) % 10; j < size; ++j) { builder.append((char)('a' + (random.nextInt() >>> 1) % 26)); } String string = builder.toString(); stringStash.add(string); if (random.nextBoolean()) { strings.intern(string); } else { strings.remove(string); } } System.out.println("################" + strings); strings.dump(); String[] stuff = randomStrings(10000); int sum = 0; Set<String> hashSet = test1(stuff); Set<String> weakInterningHashSet = test2(stuff); Set<String> weashHashMapKeySet = test3(stuff); for (int x = 0; x < 4; ++x) { { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { hashSet = test1(stuff); sum += hashSet.hashCode(); } long end = System.currentTimeMillis(); System.out.println("HashSet = " + (end - start)); } { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { weakInterningHashSet = test2(stuff); sum += weakInterningHashSet.hashCode(); } long end = System.currentTimeMillis(); System.out.println("WeakInterningHashSet = " + (end - start)); } { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { weashHashMapKeySet = test3(stuff); sum += weashHashMapKeySet.hashCode(); } long end = System.currentTimeMillis(); System.out.println("WeakHashMapKeySet = " + (end - start)); } } for (int x = 0; x < 4; ++x) { { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { for (String value : stuff) { if (hashSet.contains(value)) { ++sum; } } } long end = System.currentTimeMillis(); System.out.println("!HashSet = " + (end - start)); } { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { for (String value : stuff) { if (weakInterningHashSet.contains(value)) { ++sum; } } } long end = System.currentTimeMillis(); System.out.println("!WeakInterningHashSet = " + (end - start)); } { long start = System.currentTimeMillis(); for (int i = 0; i < 10000; ++i) { for (String value : stuff) { if (weashHashMapKeySet.contains(value)) { ++sum; } } } long end = System.currentTimeMillis(); System.out.println("!WeakHashMapKeySet = " + (end - start)); } } System.out.println("###" + sum); } public static String[] randomStrings(int count) { String[] strings = new String[count]; Random random = new Random(); for (int i = 0; i < count; ++i) { StringBuilder builder = new StringBuilder(); for (int j = 0, size = (random.nextInt() >>> 1) % 10; j < size; ++j) { builder.append((char)('a' + (random.nextInt() >>> 1) % 26)); } String string = builder.toString(); strings[i] = string; } return strings; } public static Set<String> test1(String[] strings) { Set<String> set = new HashSet<String>(); for (int i = 0; i < strings.length; ++i) { set.add(strings[i]); } return set; } public static Set<String> test3(String[] strings) { Map<String, String> set = new WeakHashMap<String, String>(); for (int i = 0; i < strings.length; ++i) { String value = strings[i]; set.put(value, value); } return set.keySet(); } public static Set<String> test2(String[] strings) { Set<String> set = new WeakInterningHashSet<String>(); for (int i = 0; i < strings.length; ++i) { set.add(strings[i]); } return set; } }