Java Tutorial/Generics/Generic Collections
Содержание
- 1 A generic first-in, first-out bounded collection of objects
- 2 A list declared to hold objects of a type T can also hold objects that extend from T.
- 3 Arrays: Storing class objects in Array as data items
- 4 Create a typesafe copy of a raw list.
- 5 Create a typesafe copy of a raw map.
- 6 Create a typesafe filter of an unchecked enumeration.
- 7 Create a typesafe filter of an unchecked iterator.
- 8 Create a typesafe view over an underlying raw map.
- 9 Create a typesafe view over an underlying raw set.
- 10 Generics and Collections: ArrayList
- 11 Generic to list
- 12 Using Generic Comparable interface
- 13 Utilities for generic ArrayList
- 14 Your own tree with generic user object
A generic first-in, first-out bounded collection of objects
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class QueueTester {
public static void main(String[] args) {
BoundedQueue<String> q = new BoundedQueue<String>(10);
q.add("A");
q.add("B");
q.add("C");
q.remove();
q.add("D");
ArrayList<String> a = new ArrayList<String>();
a.addAll(q);
System.out.println("Result of bulk add: " + a);
System.out.println("Minimum: " + Collections.min(q));
}
}
/**
* A first-in, first-out bounded collection of objects.
*/
class BoundedQueue<E> extends AbstractCollection<E> {
private Object[] elements;
private int head;
private int tail;
private int count;
public BoundedQueue(int capacity) {
elements = new Object[capacity];
count = 0;
head = 0;
tail = 0;
}
public Iterator<E> iterator() {
return new Iterator<E>() {
public boolean hasNext() {
return visited < count;
}
public E next() {
int index = (head + visited) % elements.length;
E r = (E) elements[index];
visited++;
return r;
}
public void remove() {
throw new UnsupportedOperationException();
}
private int visited = 0;
};
}
/**
* Remove object at head.
*
* @return the object that has been removed from the queue
* @precondition size() > 0
*/
public E remove() {
E r = (E) elements[head];
head = (head + 1) % elements.length;
count--;
return r;
}
/**
* Append an object at tail.
*
* @param anObject
* the object to be appended
* @return true since this operation modifies the queue. (This is a
* requirement of the collections framework.)
* @precondition !isFull()
*/
public boolean add(E anObject) {
elements[tail] = anObject;
tail = (tail + 1) % elements.length;
count++;
return true;
}
public int size() {
return count;
}
/**
* Checks whether this queue is full.
*
* @return true if the queue is full
*/
public boolean isFull() {
return count == elements.length;
}
/**
* Gets object at head.
*
* @return the object that is at the head of the queue
* @precondition size() > 0
*/
public E peek() {
return (E) elements[head];
}
}
A list declared to hold objects of a type T can also hold objects that extend from T.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] argv) {
List<Number> numlist = new ArrayList<Number>();
numlist.add(new Integer(123));
numlist.add(new Float(123));
}
}
Arrays: Storing class objects in Array as data items
class Person {
private String lastName;
private String firstName;
private int age;
public Person(String last, String first, int a) {
lastName = last;
firstName = first;
age = a;
}
public String toString() {
return "Last name: " + lastName + " First name: " + firstName + " Age: " + age;
}
public String getLast() {
return lastName;
}
}
public class MainClass {
public static void main(String[] args) {
Person[] persons = new Person[10];
for(int i=0;i<persons.length;i++){
persons[i] = new Person("A","B",10);
}
for(Person p: persons){
System.out.println(p.getLast());
}
}
}
A A A A A A A A A A
Create a typesafe copy of a raw list.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.RandomAccess;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe copy of a raw list.
* @param rawList an unchecked list
* @param type the desired supertype of the entries
* @param strict true to throw a <code>ClassCastException</code> if the raw list has an invalid entry,
* false to skip over such entries (warnings may be logged)
* @return a typed list guaranteed to contain only entries assignable
* to the named type (or they may be null)
* @throws ClassCastException if some entry in the raw list was not well-typed, and only if <code>strict</code> was true
*/
public static <E> List<E> checkedListByCopy(List rawList, Class<E> type, boolean strict) throws ClassCastException {
List<E> l = (rawList instanceof RandomAccess) ? new ArrayList<E>(rawList.size()) : new LinkedList<E>();
Iterator it = rawList.iterator();
while (it.hasNext()) {
Object e = it.next();
try {
l.add(type.cast(e));
} catch (ClassCastException x) {
if (strict) {
throw x;
} else {
System.out.println("not assignable ");
}
}
}
return l;
}
}
Create a typesafe copy of a raw map.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe copy of a raw map.
* @param rawMap an unchecked map
* @param keyType the desired supertype of the keys
* @param valueType the desired supertype of the values
* @param strict true to throw a <code>ClassCastException</code> if the raw map has an invalid key or value,
* false to skip over such map entries (warnings may be logged)
* @return a typed map guaranteed to contain only keys and values assignable
* to the named types (or they may be null)
* @throws ClassCastException if some key or value in the raw map was not well-typed, and only if <code>strict</code> was true
*/
public static <K,V> Map<K,V> checkedMapByCopy(Map rawMap, Class<K> keyType, Class<V> valueType, boolean strict) throws ClassCastException {
Map<K,V> m2 = new HashMap<K,V>(rawMap.size() * 4 / 3 + 1);
Iterator it = rawMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry e = (Map.Entry) it.next();
try {
m2.put(keyType.cast(e.getKey()), valueType.cast(e.getValue()));
} catch (ClassCastException x) {
if (strict) {
throw x;
} else {
System.out.println("not assignable");
}
}
}
return m2;
}
}
Create a typesafe filter of an unchecked enumeration.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe filter of an unchecked enumeration.
* @param rawEnum an unchecked enumeration
* @param type the desired enumeration type
* @param strict if false, elements which are not null but not assignable to the requested type are omitted;
* if true, {@link ClassCastException} may be thrown from an enumeration operation
* @return an enumeration guaranteed to contain only objects of the requested type (or null)
*/
public static <E> Enumeration<E> checkedEnumerationByFilter(Enumeration rawEnum, final Class<E> type, final boolean strict) {
@SuppressWarnings("unchecked")
Enumeration<Object> _rawEnum = rawEnum;
return Enumerations.<Object,E>filter(_rawEnum, new Enumerations.Processor<Object,E>() {
public E process(Object o, Collection<Object> ignore) {
if (o == null) {
return null;
} else {
try {
return type.cast(o);
} catch (ClassCastException x) {
if (strict) {
throw x;
} else {
return null;
}
}
}
}
});
}
}
abstract class CheckedIterator<E> implements Iterator<E> {
static final Object WAITING = new Object();
private final Iterator it;
private Object next = WAITING;
public CheckedIterator(Iterator it) {
this.it = it;
}
protected abstract boolean accept(Object o);
public boolean hasNext() {
if (next != WAITING) {
return true;
}
while (it.hasNext()) {
next = it.next();
if (accept(next)) {
return true;
}
}
next = WAITING;
return false;
}
public E next() {
if (next == WAITING && !hasNext()) {
throw new NoSuchElementException();
}
assert next != WAITING;
@SuppressWarnings("unchecked")
// type-checking is done by accept()
E x = (E) next;
next = WAITING;
return x;
}
public void remove() {
it.remove();
}
}
Create a typesafe filter of an unchecked iterator.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe filter of an unchecked iterator. {@link Iterator#remove}
* will work if it does in the unchecked iterator.
*
* @param rawIterator
* an unchecked iterator
* @param type
* the desired enumeration type
* @param strict
* if false, elements which are not null but not assignable to the
* requested type are omitted; if true, {@link ClassCastException}
* may be thrown from an iterator operation
* @return an iterator guaranteed to contain only objects of the requested
* type (or null)
*/
public static <E> Iterator<E> checkedIteratorByFilter(Iterator rawIterator, final Class<E> type,
final boolean strict) {
return new CheckedIterator<E>(rawIterator) {
protected boolean accept(Object o) {
if (o == null) {
return true;
} else if (type.isInstance(o)) {
return true;
} else if (strict) {
throw new ClassCastException(o + " was not a " + type.getName()); // NOI18N
} else {
return false;
}
}
};
}
}
abstract class CheckedIterator<E> implements Iterator<E> {
static final Object WAITING = new Object();
private final Iterator it;
private Object next = WAITING;
public CheckedIterator(Iterator it) {
this.it = it;
}
protected abstract boolean accept(Object o);
public boolean hasNext() {
if (next != WAITING) {
return true;
}
while (it.hasNext()) {
next = it.next();
if (accept(next)) {
return true;
}
}
next = WAITING;
return false;
}
public E next() {
if (next == WAITING && !hasNext()) {
throw new NoSuchElementException();
}
assert next != WAITING;
@SuppressWarnings("unchecked")
// type-checking is done by accept()
E x = (E) next;
next = WAITING;
return x;
}
public void remove() {
it.remove();
}
}
Create a typesafe view over an underlying raw map.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe view over an underlying raw map.
* Mutations affect the underlying map (this is not a copy).
* {@link Map#clear} will make the view empty but may not clear the underlying map.
* You may add entries only of the requested type pair.
* {@link Map#get}, {@link Map#containsKey}, and {@link Map#containsValue} also perform a type check
* and will throw {@link ClassCastException} for an illegal argument.
* The view is serializable if the underlying map is.
* @param rawMap an unchecked map
* @param keyType the desired entry key type
* @param valueType the desired entry value type
* @param strict if false, entries in the underlying map for which the key is not null but not assignable
* to the requested key type, and/or the value is not null but not assignable to
* the requested value type, are omitted from the view;
* if true, a {@link ClassCastException} may arise during some map operation
* @return a view over the raw map guaranteed to match the specified type
*/
public static <K,V> Map<K,V> checkedMapByFilter(Map rawMap, Class<K> keyType, Class<V> valueType, boolean strict) {
return new CheckedMap<K,V>(rawMap, keyType, valueType, strict);
}
private static final class CheckedMap<K,V> extends AbstractMap<K,V> implements Serializable {
private static final long serialVersionUID = 1L;
private final Map rawMap;
private final Class<K> keyType;
private final Class<V> valueType;
private final boolean strict;
public CheckedMap(Map rawMap, Class<K> keyType, Class<V> valueType, boolean strict) {
this.rawMap = rawMap;
this.keyType = keyType;
this.valueType = valueType;
this.strict = strict;
}
private boolean acceptKey(Object o) {
if (o == null) {
return true;
} else if (keyType.isInstance(o)) {
return true;
} else if (strict) {
throw new ClassCastException(o + " was not a " + keyType.getName()); // NOI18N
} else {
return false;
}
}
private boolean acceptValue(Object o) {
if (o == null) {
return true;
} else if (valueType.isInstance(o)) {
return true;
} else if (strict) {
throw new ClassCastException(o + " was not a " + valueType.getName()); // NOI18N
} else {
return false;
}
}
private boolean acceptEntry(Map.Entry e) {
return acceptKey(e.getKey()) && acceptValue(e.getValue());
}
private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new CheckedIterator<Map.Entry<K,V>>(rawMap.entrySet().iterator()) {
@Override
protected boolean accept(Object o) {
return acceptEntry((Map.Entry) o);
}
};
}
@Override
public int size() {
int c = 0;
Iterator it = rawMap.entrySet().iterator();
while (it.hasNext()) {
if (acceptEntry((Map.Entry) it.next())) {
c++;
}
}
return c;
}
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
return new EntrySet();
}
@Override
public V get(Object key) {
Object o = rawMap.get(keyType.cast(key));
if (acceptValue(o)) {
@SuppressWarnings("unchecked")
V v = (V) o;
return v;
} else {
return null;
}
}
@SuppressWarnings("unchecked")
@Override
public V put(K key, V value) {
Object old = rawMap.put(keyType.cast(key), valueType.cast(value));
if (acceptValue(old)) {
return (V) old;
} else {
return null;
}
}
@Override
public V remove(Object key) {
Object old = rawMap.remove(keyType.cast(key));
if (acceptValue(old)) {
@SuppressWarnings("unchecked")
V v = (V) old;
return v;
} else {
return null;
}
}
@Override
public boolean containsKey(Object key) {
return rawMap.containsKey(keyType.cast(key)) &&
acceptValue(rawMap.get(key));
}
@Override
public boolean containsValue(Object value) {
// Cannot just ask rawMap since we could not check type of key.
return super.containsValue(valueType.cast(value));
}
@Override
public int size() {
int c = 0;
Iterator it = rawMap.entrySet().iterator();
while (it.hasNext()) {
if (acceptEntry((Map.Entry) it.next())) {
c++;
}
}
return c;
}
// keySet, values cannot be so easily overridden because we type-check whole entries
}
}
abstract class CheckedIterator<E> implements Iterator<E> {
static final Object WAITING = new Object();
private final Iterator it;
private Object next = WAITING;
public CheckedIterator(Iterator it) {
this.it = it;
}
protected abstract boolean accept(Object o);
public boolean hasNext() {
if (next != WAITING) {
return true;
}
while (it.hasNext()) {
next = it.next();
if (accept(next)) {
return true;
}
}
next = WAITING;
return false;
}
public E next() {
if (next == WAITING && !hasNext()) {
throw new NoSuchElementException();
}
assert next != WAITING;
@SuppressWarnings("unchecked")
// type-checking is done by accept()
E x = (E) next;
next = WAITING;
return x;
}
public void remove() {
it.remove();
}
}
Create a typesafe view over an underlying raw set.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License. When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe view over an underlying raw set.
* Mutations affect the underlying set (this is not a copy).
* {@link Set#clear} will make the view empty but may not clear the underlying set.
* You may add elements only of the requested type.
* {@link Set#contains} also performs a type check and will throw {@link ClassCastException}
* for an illegal argument.
* The view is serializable if the underlying set is.
* @param rawSet an unchecked set
* @param type the desired element type
* @param strict if false, elements in the underlying set which are not null and which are not assignable
* to the requested type are omitted from the view;
* if true, a {@link ClassCastException} may arise during some set operation
* @return a view over the raw set guaranteed to match the specified type
*/
public static <E> Set<E> checkedSetByFilter(Set rawSet, Class<E> type, boolean strict) {
return new CheckedSet<E>(rawSet, type, strict);
}
private static final class CheckedSet<E> extends AbstractSet<E> implements Serializable {
private static final long serialVersionUID = 1L;
private final Set rawSet;
private final Class<E> type;
private final boolean strict;
public CheckedSet(Set rawSet, Class<E> type, boolean strict) {
this.rawSet = rawSet;
this.type = type;
this.strict = strict;
}
private boolean acceptEntry(Object o) {
if (o == null) {
return true;
} else if (type.isInstance(o)) {
return true;
} else if (strict) {
throw new ClassCastException(o + " was not a " + type.getName()); // NOI18N
} else {
return false;
}
}
@Override
public Iterator<E> iterator() {
return new CheckedIterator<E>(rawSet.iterator()) {
@Override
protected boolean accept(Object o) {
return acceptEntry(o);
}
};
}
@Override
public int size() {
int c = 0;
Iterator it = rawSet.iterator();
while (it.hasNext()) {
if (acceptEntry(it.next())) {
c++;
}
}
return c;
}
@Override
@SuppressWarnings("unchecked") // complains about usage of raw set
public boolean add(E o) {
return rawSet.add(type.cast(o));
}
@Override
public boolean contains(Object o) {
return rawSet.contains(type.cast(o));
}
}
}
abstract class CheckedIterator<E> implements Iterator<E> {
static final Object WAITING = new Object();
private final Iterator it;
private Object next = WAITING;
public CheckedIterator(Iterator it) {
this.it = it;
}
protected abstract boolean accept(Object o);
public boolean hasNext() {
if (next != WAITING) {
return true;
}
while (it.hasNext()) {
next = it.next();
if (accept(next)) {
return true;
}
}
next = WAITING;
return false;
}
public E next() {
if (next == WAITING && !hasNext()) {
throw new NoSuchElementException();
}
assert next != WAITING;
@SuppressWarnings("unchecked")
// type-checking is done by accept()
E x = (E) next;
next = WAITING;
return x;
}
public void remove() {
it.remove();
}
}
Generics and Collections: ArrayList
import java.util.ArrayList;
import java.util.Iterator;
public class MainClass {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
Iterator<String> itr = list.iterator();
while(itr.hasNext()) {
String str = itr.next();
System.out.println(str + " is " + str.length() + " chars long.");
}
}
}
one is 3 chars long. two is 3 chars long. three is 5 chars long. four is 4 chars long.
Generic to list
/*
Milyn - Copyright (C) 2006
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (version 2.1) as published by the Free Software
Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details:
http://www.gnu.org/licenses/lgpl.txt
*/
import java.util.*;
/**
* Collections Utilities.
*
* @author
*/
public class CollectionsUtil {
/**
* Private constructor.
*/
private CollectionsUtil() {
}
/**
* Create an Object {@link Set} from the supplied objects.
* @param objects The objects to be added to the set.
* @return The {@link Set}.
*/
public static <T> Set<T> toSet(T... objects) {
Set<T> theSet = new HashSet<T>();
addToCollection(theSet, objects);
return theSet;
}
/**
* Create an Object {@link List} from the supplied objects.
* @param objects The objects to be added to the list.
* @return The {@link List}.
*/
public static <T> List<T> toList(T... objects) {
List<T> theSet = new ArrayList<T>();
addToCollection(theSet, objects);
return theSet;
}
private static <T> void addToCollection(Collection<T> theCollection, T... objects) {
for(T object : objects) {
theCollection.add(object);
}
}
}
Using Generic Comparable interface
import java.util.Arrays;
class Person implements Comparable<Person> {
public Person(String firstName, String surname) {
this.firstName = firstName;
this.surname = surname;
}
public String toString() {
return firstName + " " + surname;
}
public int compareTo(Person person) {
int result = surname.rupareTo(person.surname);
return result == 0 ? firstName.rupareTo(((Person) person).firstName) : result;
}
private String firstName;
private String surname;
}
public class MainClass {
public static void main(String[] args) {
Person[] authors = {
new Person("D", "S"),
new Person("J", "G"),
new Person("T", "C"),
new Person("C", "S"),
new Person("P", "C"),
new Person("B", "B") };
Arrays.sort(authors); // Sort using Comparable method
System.out.println("\nOrder after sorting into ascending sequence:");
for (Person author : authors) {
System.out.println(author);
}
Person[] people = {
new Person("C", "S"),
new Person("N", "K"),
new Person("T", "C"),
new Person("C", "D") };
int index = 0;
System.out.println("\nIn search of authors:");
for (Person person : people) {
index = Arrays.binarySearch(authors, person);
if (index >= 0) {
System.out.println(person + " was found at index position " + index);
} else {
System.out.println(person + "was not found. Return value is " + index);
}
}
}
}
Order after sorting into ascending sequence: B B P C T C J G C S D S In search of authors: C S was found at index position 4 N Kwas not found. Return value is -5 T C was found at index position 2 C Dwas not found. Return value is -4
Utilities for generic ArrayList
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.ArrayList;
import java.util.GregorianCalendar;
public class UtilsTester {
public static void main(String[] args) throws InstantiationException,
IllegalAccessException {
ArrayList<String> ids = new ArrayList<String>();
Utils.fill(ids, "default", 10);
System.out.println(ids);
ArrayList<Shape> shapes = new ArrayList<Shape>();
Utils.fill(shapes, new Rectangle(5, 10, 20, 30), 2);
System.out.println(shapes);
ArrayList<Polygon> polys = new ArrayList<Polygon>();
Utils.fillWithDefaults(polys, Polygon.class, 10);
Utils.append(shapes, polys, 2);
System.out.println(shapes);
ArrayList<GregorianCalendar> dates = new ArrayList<GregorianCalendar>();
Utils.fillWithDefaults(dates, GregorianCalendar.class, 5);
System.out.println(Utils.getMax(dates));
}
}
class Utils {
public static <E> void fill(ArrayList<E> a, E value, int count) {
for (int i = 0; i < count; i++)
a.add(value);
}
public static <E, F extends E> void append(ArrayList<E> a, ArrayList<F> b,
int count) {
for (int i = 0; i < count && i < b.size(); i++)
a.add(b.get(i));
}
public static <E extends Comparable<? super E>> E getMax(ArrayList<E> a) {
E max = a.get(0);
for (int i = 1; i < a.size(); i++)
if (a.get(i).rupareTo(max) > 0)
max = a.get(i);
return max;
}
public static <E> void fillWithDefaults(ArrayList<E> a,
Class<? extends E> cl, int count) throws InstantiationException,
IllegalAccessException {
for (int i = 0; i < count; i++)
a.add(cl.newInstance());
}
}
Your own tree with generic user object
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
/**
* @author ycoppel@google.ru (Yohann Coppel)
*
* @param <T>
* Object"s type in the tree.
*/
public class Tree<T> {
private T head;
private ArrayList<Tree<T>> leafs = new ArrayList<Tree<T>>();
private Tree<T> parent = null;
private HashMap<T, Tree<T>> locate = new HashMap<T, Tree<T>>();
public Tree(T head) {
this.head = head;
locate.put(head, this);
}
public void addLeaf(T root, T leaf) {
if (locate.containsKey(root)) {
locate.get(root).addLeaf(leaf);
} else {
addLeaf(root).addLeaf(leaf);
}
}
public Tree<T> addLeaf(T leaf) {
Tree<T> t = new Tree<T>(leaf);
leafs.add(t);
t.parent = this;
t.locate = this.locate;
locate.put(leaf, t);
return t;
}
public Tree<T> setAsParent(T parentRoot) {
Tree<T> t = new Tree<T>(parentRoot);
t.leafs.add(this);
this.parent = t;
t.locate = this.locate;
t.locate.put(head, this);
t.locate.put(parentRoot, t);
return t;
}
public T getHead() {
return head;
}
public Tree<T> getTree(T element) {
return locate.get(element);
}
public Tree<T> getParent() {
return parent;
}
public Collection<T> getSuccessors(T root) {
Collection<T> successors = new ArrayList<T>();
Tree<T> tree = getTree(root);
if (null != tree) {
for (Tree<T> leaf : tree.leafs) {
successors.add(leaf.head);
}
}
return successors;
}
public Collection<Tree<T>> getSubTrees() {
return leafs;
}
public static <T> Collection<T> getSuccessors(T of, Collection<Tree<T>> in) {
for (Tree<T> tree : in) {
if (tree.locate.containsKey(of)) {
return tree.getSuccessors(of);
}
}
return new ArrayList<T>();
}
@Override
public String toString() {
return printTree(0);
}
private static final int indent = 2;
private String printTree(int increment) {
String s = "";
String inc = "";
for (int i = 0; i < increment; ++i) {
inc = inc + " ";
}
s = inc + head;
for (Tree<T> child : leafs) {
s += "\n" + child.printTree(increment + indent);
}
return s;
}
}