Java/Generics/Generic Collection
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 A list declared to hold objects of a type T can also hold objects that extend from T.
- 2 A value retrieved from a type-specific list does not need to be casted
- 3 Circular Object Buffer
- 4 Collections and Data structure: the generic way
- 5 Create a typesafe copy of a raw list.
- 6 Create a typesafe copy of a raw map.
- 7 Create a typesafe copy of a raw set.
- 8 Create a typesafe filter of an unchecked enumeration.
- 9 Create a typesafe filter of an unchecked iterator.
- 10 Create a typesafe view over an underlying raw map.
- 11 Create a typesafe view over an underlying raw set.
- 12 Creating a Type-Specific List
- 13 Data structure and collections: Modern, generics version.
- 14 Enum and Generic
- 15 Foreach and generic data structure
- 16 Generic ArrayList
- 17 Generic Data Structure
- 18 Generic HashMap
- 19 Generic Stack
- 20 Java generic: Generics and arrays.
- 21 Pre generics example that uses a collection.
- 22 The GenStack Class
- 23 Unchecked Example
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));
}
}
A value retrieved from a type-specific list does not need to be casted
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] argv) {
List<URL> urlList = new ArrayList<URL>();
try {
urlList.add(new URL("http://www.jexp.ru"));
} catch (MalformedURLException e) {
}
String s = urlList.get(0).getHost();
}
}
Circular Object Buffer
/*
* Circular Object Buffer
* Copyright (C) 2002-2004 Stephen Ostermiller
* http://ostermiller.org/contact.pl?regarding=Java+Utilities
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* See COPYING.TXT for details.
*/
/**
* Implements the Circular Buffer producer/consumer model for Objects.
* More information about this class is available from .
* <p>
* This class is thread safe.
*
* @see CircularCharBuffer
* @see CircularByteBuffer
*
* @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
* @param <ElementType> Type of object allowed in this circular buffer
* @since ostermillerutils 1.00.00
*/
public class CircularObjectBuffer <ElementType> {
/**
* The default size for a circular object buffer.
*
* @since ostermillerutils 1.00.00
*/
private final static int DEFAULT_SIZE = 1024;
/**
* A buffer that will grow as things are added.
*
* @since ostermillerutils 1.00.00
*/
public final static int INFINITE_SIZE = -1;
/**
* The circular buffer.
* <p>
* The actual capacity of the buffer is one less than the actual length
* of the buffer so that an empty and a full buffer can be
* distinguished. An empty buffer will have the readPostion and the
* writePosition equal to each other. A full buffer will have
* the writePosition one less than the readPostion.
* <p>
* There are two important indexes into the buffer:
* The readPosition, and the writePosition. The Objects
* available to be read go from the readPosition to the writePosition,
* wrapping around the end of the buffer. The space available for writing
* goes from the write position to one less than the readPosition,
* wrapping around the end of the buffer.
*
* @since ostermillerutils 1.00.00
*/
protected ElementType[] buffer;
/**
* Index of the first Object available to be read.
*
* @since ostermillerutils 1.00.00
*/
protected volatile int readPosition = 0;
/**
* Index of the first Object available to be written.
*
* @since ostermillerutils 1.00.00
*/
protected volatile int writePosition = 0;
/**
* If this buffer is infinite (should resize itself when full)
*
* @since ostermillerutils 1.00.00
*/
protected volatile boolean infinite = false;
/**
* True if a write to a full buffer should block until the buffer
* has room, false if the write method should throw an IOException
*
* @since ostermillerutils 1.00.00
*/
protected boolean blockingWrite = true;
/**
* True when no more input is coming into this buffer. At that
* point reading from the buffer may return null if the buffer
* is empty, otherwise a read will block until an Object is available.
*
* @since ostermillerutils 1.00.00
*/
protected boolean inputDone = false;
/**
* Make this buffer ready for reuse. The contents of the buffer
* will be cleared and the streams associated with this buffer
* will be reopened if they had been closed.
*
* @since ostermillerutils 1.00.00
*/
public void clear(){
synchronized (this){
readPosition = 0;
writePosition = 0;
inputDone = false;
}
}
/**
* Get number of Objects that are available to be read.
* <p>
* Note that the number of Objects available plus
* the number of Objects free may not add up to the
* capacity of this buffer, as the buffer may reserve some
* space for other purposes.
*
* @return the size in Objects of this buffer
*
* @since ostermillerutils 1.00.00
*/
public int getAvailable(){
synchronized (this){
return available();
}
}
/**
* Get the number of Objects this buffer has free for
* writing.
* <p>
* Note that the number of Objects available plus
* the number of Objects free may not add up to the
* capacity of this buffer, as the buffer may reserve some
* space for other purposes.
*
* @return the available space in Objects of this buffer
*
* @since ostermillerutils 1.00.00
*/
public int getSpaceLeft(){
synchronized (this){
return spaceLeft();
}
}
/**
* Get the capacity of this buffer.
* <p>
* Note that the number of Objects available plus
* the number of Objects free may not add up to the
* capacity of this buffer, as the buffer may reserve some
* space for other purposes.
*
* @return the size in Objects of this buffer
*
* @since ostermillerutils 1.00.00
*/
public int getSize(){
synchronized (this){
return buffer.length;
}
}
@SuppressWarnings("unchecked") private ElementType[] createArray(int size){
return (ElementType[]) new Object[size];
}
/**
* double the size of the buffer
*
* @since ostermillerutils 1.00.00
*/
private void resize(){
ElementType[] newBuffer = createArray(buffer.length * 2);
int available = available();
if (readPosition <= writePosition){
// any space between the read and
// the first write needs to be saved.
// In this case it is all in one piece.
int length = writePosition - readPosition;
System.arraycopy(buffer, readPosition, newBuffer, 0, length);
} else {
int length1 = buffer.length - readPosition;
System.arraycopy(buffer, readPosition, newBuffer, 0, length1);
int length2 = writePosition;
System.arraycopy(buffer, 0, newBuffer, length1, length2);
}
buffer = newBuffer;
readPosition = 0;
writePosition = available;
}
/**
* Space available in the buffer which can be written.
*
* @since ostermillerutils 1.00.00
*/
private int spaceLeft(){
if (writePosition < readPosition){
// any space between the first write and
// the read except one Object is available.
// In this case it is all in one piece.
return (readPosition - writePosition - 1);
}
// space at the beginning and end.
return ((buffer.length - 1) - (writePosition - readPosition));
}
/**
* Objects available for reading.
*
* @since ostermillerutils 1.00.00
*/
private int available(){
if (readPosition <= writePosition){
// any space between the first read and
// the first write is available. In this case i
// is all in one piece.
return (writePosition - readPosition);
}
// space at the beginning and end.
return (buffer.length - (readPosition - writePosition));
}
/**
* Create a new buffer with a default capacity.
* Writing to a full buffer will block until space
* is available rather than throw an exception.
*
* @since ostermillerutils 1.00.00
*/
public CircularObjectBuffer(){
this (DEFAULT_SIZE, true);
}
/**
* Create a new buffer with given capacity.
* Writing to a full buffer will block until space
* is available rather than throw an exception.
* <p>
* Note that the buffer may reserve some Objects for
* special purposes and capacity number of Objects may
* not be able to be written to the buffer.
* <p>
* Note that if the buffer is of INFINITE_SIZE it will
* neither block or throw exceptions, but rather grow
* without bound.
*
* @param size desired capacity of the buffer in Objects or CircularObjectBuffer.INFINITE_SIZE.
*
* @since ostermillerutils 1.00.00
*/
public CircularObjectBuffer(int size){
this (size, true);
}
/**
* Create a new buffer with a default capacity and
* given blocking behavior.
*
* @param blockingWrite true writing to a full buffer should block
* until space is available, false if an exception should
* be thrown instead.
*
* @since ostermillerutils 1.00.00
*/
public CircularObjectBuffer(boolean blockingWrite){
this (DEFAULT_SIZE, blockingWrite);
}
/**
* Create a new buffer with the given capacity and
* blocking behavior.
* <p>
* Note that the buffer may reserve some Objects for
* special purposes and capacity number of Objects may
* not be able to be written to the buffer.
* <p>
* Note that if the buffer is of INFINITE_SIZE it will
* neither block or throw exceptions, but rather grow
* without bound.
*
* @param size desired capacity of the buffer in Objects or CircularObjectBuffer.INFINITE_SIZE.
* @param blockingWrite true writing to a full buffer should block
* until space is available, false if an exception should
* be thrown instead.
*
* @since ostermillerutils 1.00.00
*/
public CircularObjectBuffer(int size, boolean blockingWrite){
if (size == INFINITE_SIZE){
buffer = createArray(DEFAULT_SIZE);
infinite = true;
} else {
buffer = createArray(size);
infinite = false;
}
this.blockingWrite = blockingWrite;
}
/**
* Get a single Object from this buffer. This method should be called
* by the consumer.
* This method will block until a Object is available or no more
* objects are available.
*
* @return The Object read, or null if there are no more objects
* @throws InterruptedException if the thread is interrupted while waiting.
*
* @since ostermillerutils 1.00.00
*/
public ElementType read() throws InterruptedException {
while (true){
synchronized (this){
int available = available();
if (available > 0){
ElementType result = buffer[readPosition];
readPosition++;
if (readPosition == buffer.length){
readPosition = 0;
}
return result;
} else if (inputDone){
return null;
}
}
Thread.sleep(100);
}
}
/**
* Get Objects into an array from this buffer. This method should
* be called by the consumer.
* This method will block until some input is available,
* or there is no more input.
*
* @param buf Destination buffer.
* @return The number of Objects read, or -1 there will
* be no more objects available.
* @throws InterruptedException if the thread is interrupted while waiting.
*
* @since ostermillerutils 1.00.00
*/
public int read(ElementType[] buf) throws InterruptedException {
return read(buf, 0, buf.length);
}
/**
* Get Objects into a portion of an array from this buffer. This
* method should be called by the consumer.
* This method will block until some input is available,
* an I/O error occurs, or the end of the stream is reached.
*
* @param buf Destination buffer.
* @param off Offset at which to start storing Objects.
* @param len Maximum number of Objects to read.
* @return The number of Objects read, or -1 there will
* be no more objects available.
* @throws InterruptedException if the thread is interrupted while waiting.
*
* @since ostermillerutils 1.00.00
*/
public int read(ElementType[] buf, int off, int len) throws InterruptedException {
while (true){
synchronized (this){
int available = available();
if (available > 0){
int length = Math.min(len, available);
int firstLen = Math.min(length, buffer.length - readPosition);
int secondLen = length - firstLen;
System.arraycopy(buffer, readPosition, buf, off, firstLen);
if (secondLen > 0){
System.arraycopy(buffer, 0, buf, off+firstLen, secondLen);
readPosition = secondLen;
} else {
readPosition += length;
}
if (readPosition == buffer.length) {
readPosition = 0;
}
return length;
} else if (inputDone){
return -1;
}
}
Thread.sleep(100);
}
}
/**
* Skip Objects. This method should be used by the consumer
* when it does not care to examine some number of Objects.
* This method will block until some Objects are available,
* or there will be no more Objects available.
*
* @param n The number of Objects to skip
* @return The number of Objects actually skipped
* @throws IllegalArgumentException if n is negative.
* @throws InterruptedException if the thread is interrupted while waiting.
*
* @since ostermillerutils 1.00.00
*/
public long skip(long n) throws InterruptedException, IllegalArgumentException {
while (true){
synchronized (this){
int available = available();
if (available > 0){
int length = Math.min((int)n, available);
int firstLen = Math.min(length, buffer.length - readPosition);
int secondLen = length - firstLen;
if (secondLen > 0){
readPosition = secondLen;
} else {
readPosition += length;
}
if (readPosition == buffer.length) {
readPosition = 0;
}
return length;
} else if (inputDone){
return 0;
}
}
Thread.sleep(100);
}
}
/**
* This method should be used by the producer to signal to the consumer
* that the producer is done producing objects and that the consumer
* should stop asking for objects once it has used up buffered objects.
* <p>
* Once the producer has signaled that it is done, further write() invocations
* will cause an IllegalStateException to be thrown. Calling done() multiple times,
* however, has no effect.
*
* @since ostermillerutils 1.00.00
*/
public void done(){
synchronized (this){
inputDone = true;
}
}
/**
* Fill this buffer with array of Objects. This method should be called
* by the producer.
* If the buffer allows blocking writes, this method will block until
* all the data has been written rather than throw a BufferOverflowException.
*
* @param buf Array of Objects to be written
* @throws BufferOverflowException if buffer does not allow blocking writes
* and the buffer is full. If the exception is thrown, no data
* will have been written since the buffer was set to be non-blocking.
* @throws IllegalStateException if done() has been called.
* @throws InterruptedException if the write is interrupted.
*
* @since ostermillerutils 1.00.00
*/
public void write(ElementType[] buf) throws Exception{
write(buf, 0, buf.length);
}
/**
* Fill this buffer with a portion of an array of Objects.
* This method should be called by the producer.
* If the buffer allows blocking writes, this method will block until
* all the data has been written rather than throw an IOException.
*
* @param buf Array of Objects
* @param off Offset from which to start writing Objects
* @param len - Number of Objects to write
* @throws BufferOverflowException if buffer does not allow blocking writes
* and the buffer is full. If the exception is thrown, no data
* will have been written since the buffer was set to be non-blocking.
* @throws IllegalStateException if done() has been called.
* @throws InterruptedException if the write is interrupted.
*
* @since ostermillerutils 1.00.00
*/
public void write(ElementType[] buf, int off, int len) throws Exception{
while (len > 0){
synchronized (CircularObjectBuffer.this){
if (inputDone) throw new IllegalStateException("CircularObjectBuffer.done() has been called, CircularObjectBuffer.write() failed.");
int spaceLeft = spaceLeft();
while (infinite && spaceLeft < len){
resize();
spaceLeft = spaceLeft();
}
if (!blockingWrite && spaceLeft < len) throw new Exception("CircularObjectBuffer is full; cannot write " + len + " Objects");
int realLen = Math.min(len, spaceLeft);
int firstLen = Math.min(realLen, buffer.length - writePosition);
int secondLen = Math.min(realLen - firstLen, buffer.length - readPosition - 1);
int written = firstLen + secondLen;
if (firstLen > 0){
System.arraycopy(buf, off, buffer, writePosition, firstLen);
}
if (secondLen > 0){
System.arraycopy(buf, off+firstLen, buffer, 0, secondLen);
writePosition = secondLen;
} else {
writePosition += written;
}
if (writePosition == buffer.length) {
writePosition = 0;
}
off += written;
len -= written;
}
if (len > 0){
Thread.sleep(100);
}
}
}
/**
* Add a single Object to this buffer. This method should be
* called by the producer.
* If the buffer allows blocking writes, this method will block until
* all the data has been written rather than throw an IOException.
*
* @param o Object to be written.
* @throws BufferOverflowException if buffer does not allow blocking writes
* and the buffer is full. If the exception is thrown, no data
* will have been written since the buffer was set to be non-blocking.
* @throws IllegalStateException if done() has been called.
* @throws InterruptedException if the write is interrupted.
*
* @since ostermillerutils 1.00.00
*/
public void write(ElementType o) throws Exception{
boolean written = false;
while (!written){
synchronized (CircularObjectBuffer.this){
if (inputDone) throw new IllegalStateException("CircularObjectBuffer.done() has been called, CircularObjectBuffer.write() failed.");
int spaceLeft = spaceLeft();
while (infinite && spaceLeft < 1){
resize();
spaceLeft = spaceLeft();
}
if (!blockingWrite && spaceLeft < 1) throw new Exception("CircularObjectBuffer is full; cannot write 1 Object");
if (spaceLeft > 0){
buffer[writePosition] = o;
writePosition++;
if (writePosition == buffer.length) {
writePosition = 0;
}
written = true;
}
}
if (!written){
Thread.sleep(100);
}
}
}
}
Collections and Data structure: the generic way
/*
License for Java 1.5 "Tiger": A Developer"s Notebook
(O"Reilly) example package
Java 1.5 "Tiger": A Developer"s Notebook (O"Reilly)
by Brett McLaughlin and David Flanagan.
ISBN: 0-596-00738-8
You can use the examples and the source code any way you want, but
please include a reference to where it comes from if you use it in
your own products or services. Also note that this software is
provided by the author "as is", with no expressed or implied warranties.
In no event shall the author be liable for any direct or indirect
damages arising in any way out of the use of this software.
*/
import java.util.ArrayList;
import java.io.IOException;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class GenericsTester {
public GenericsTester() {
}
public void testTypeSafeMaps(PrintStream out) throws IOException {
Map<Integer, Integer> squares = new HashMap<Integer, Integer>();
for (int i=0; i<100; i++) {
squares.put(i, i*i);
}
for (int i=0; i<10; i++) {
int n = i*3;
out.println("The square of " + n + " is " + squares.get(n));
}
}
public void testTypeSafeLists(PrintStream out) throws IOException {
List listOfStrings = getListOfStrings();
for (Iterator i = listOfStrings.iterator(); i.hasNext(); ) {
String item = (String)i.next();
// Work with that string
}
List<String> onlyStrings = new LinkedList<String>();
onlyStrings.add("Legal addition");
/**
* Uncomment these two lines for an error
onlyStrings.add(new StringBuilder("Illegal Addition"));
onlyStrings.add(25);
*/
}
public void testTypeSafeIterators(PrintStream out) throws IOException {
List<String> listOfStrings = new LinkedList<String>();
listOfStrings.add("Happy");
listOfStrings.add("Birthday");
listOfStrings.add("To");
listOfStrings.add("You");
for (Iterator<String> i = listOfStrings.iterator(); i.hasNext(); ) {
String s = i.next();
out.println(s);
}
printListOfStrings(getListOfStrings(), out);
}
private List getList() {
List list = new LinkedList();
list.add(3);
list.add("Blind");
list.add("Mice");
return list;
}
private List<String> getListOfStrings() {
List<String> list = new LinkedList<String>();
list.add("Hello");
list.add("World");
list.add("How");
list.add("Are");
list.add("You?");
return list;
}
public void testTypeSafeReturnValues(PrintStream out) throws IOException {
List<String> strings = getListOfStrings();
for (String s : strings) {
out.println(s);
}
}
private void printListOfStrings(List<String> list, PrintStream out)
throws IOException {
for (Iterator<String> i = list.iterator(); i.hasNext(); ) {
out.println(i.next());
}
}
public void printList(List<?> list, PrintStream out) throws IOException {
for (Iterator<?> i = list.iterator(); i.hasNext(); ) {
out.println(i.next().toString());
}
}
public static void main(String[] args) {
GenericsTester tester = new GenericsTester();
try {
tester.testTypeSafeLists(System.out);
tester.testTypeSafeMaps(System.out);
tester.testTypeSafeIterators(System.out);
tester.testTypeSafeReturnValues(System.out);
List<Integer> ints = new LinkedList<Integer>();
ints.add(1);
ints.add(2);
ints.add(3);
tester.printList(ints, System.out);
/** Uncomment for an error
NumberBox<String> illegal = new NumberBox<String>();
*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
class NumberBox<N extends Number> extends Box<N> {
public NumberBox() {
super();
}
// Sum everything in the box
public double sum() {
double total = 0;
for (Iterator<N> i = contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue();
}
return total;
}
public static <A extends Number> double sum(Box<A> box1,
Box<A> box2) {
double total = 0;
for (Iterator<A> i = box1.contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue();
}
for (Iterator<A> i = box2.contents.iterator(); i.hasNext(); ) {
total = total + i.next().doubleValue();
}
return total;
}
}
class Box<T> {
protected List<T> contents;
public Box() {
contents = new ArrayList<T>();
}
public int getSize() {
return contents.size();
}
public boolean isEmpty() {
return (contents.size() == 0);
}
public void add(T o) {
contents.add(o);
}
public T grab() {
if (!isEmpty()) {
return contents.remove(0);
} else
return null;
}
}
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 copy of a 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.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
/**
* Create a typesafe copy of a raw set.
* @param rawSet an unchecked set
* @param type the desired supertype of the entries
* @param strict true to throw a <code>ClassCastException</code> if the raw set has an invalid entry,
* false to skip over such entries (warnings may be logged)
* @return a typed set guaranteed to contain only entries assignable
* to the named type (or they may be null)
* @throws ClassCastException if some entry in the raw set was not well-typed, and only if <code>strict</code> was true
*/
public static <E> Set<E> checkedSetByCopy(Set rawSet, Class<E> type, boolean strict) throws ClassCastException {
Set<E> s = new HashSet<E>(rawSet.size() * 4 / 3 + 1);
Iterator it = rawSet.iterator();
while (it.hasNext()) {
Object e = it.next();
try {
s.add(type.cast(e));
} catch (ClassCastException x) {
if (strict) {
throw x;
} else {
System.out.println("not assignable ");
}
}
}
return s;
}
}
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();
}
}
Creating a Type-Specific List
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] argv) {
List<Integer> intlist = new ArrayList<Integer>();
intlist.add(new Integer(123));
}
}
Data structure and collections: Modern, generics version.
/*
Java 2, v5.0 (Tiger) New Features
by Herbert Schildt
ISBN: 0072258543
Publisher: McGraw-Hill/Osborne, 2004
*/
import java.util.*;
public class NewStyle {
public static void main(String args[]) {
// Now, list holds references of type String.
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
// Notice that Iterator is also generic.
Iterator<String> itr = list.iterator();
// The following statement will now cause a compile-time eror.
// Iterator<Integer> itr = list.iterator(); // Error!
while(itr.hasNext()) {
String str = itr.next(); // no cast needed
// Now, the following line is a compile-time,
// rather than runtime, error.
// Integer i = itr.next(); // this won"t compile
System.out.println(str + " is " + str.length() + " chars long.");
}
}
}
Enum and Generic
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* MediaInvoicer - Simple applicatin of Media, MediaFactory &c.
*
* @author ian
* @version $Id: MediaInvoicer.java,v 1.2 2004/03/08 03:30:59 ian Exp $
*/
public class MediaInvoicer {
public static void main(String[] args) throws IOException {
MediaInvoicer mi = new MediaInvoicer(System.in);
Invoice i = mi.getInvoice();
i.print(System.out);
}
BufferedReader myFile;
public MediaInvoicer(InputStream is) {
myFile = new BufferedReader(new InputStreamReader(is));
}
public Invoice getInvoice() throws IOException {
String line;
List < Item > items = new ArrayList < Item > ();
while ((line = myFile.readLine()) != null) {
if (line.startsWith("#")) {
continue;
}
StringTokenizer st = new StringTokenizer(line);
st.nextToken();
Media m = MediaFactory.getMedia(st.nextToken());
int stock = Integer.parseInt(st.nextToken());
int qty = Integer.parseInt(st.nextToken());
Item tmp = new Item(m, stock, qty);
items.add(tmp);
}
return new Invoice(1, 3,
(Item[]) items.toArray(new Item[items.size()]));
}
/** Inner class for line order item */
class Item {
Media product;
int stockNumber;
int quantity;
/**
* @param product
* @param stockNumber
* @param quantity
*/
public Item(Media product, int stockNumber, int quantity) {
super();
this.product = product;
this.stockNumber = stockNumber;
this.quantity = quantity;
}
public String toString() {
return "Item[" + product + " " + stockNumber + "]";
}
}
/** Inner class for one invoice */
class Invoice {
int orderNumber;
int custNumber;
Item[] items;
public Invoice(int orderNumber, int custNumber, Item[] items) {
super();
this.orderNumber = orderNumber;
this.custNumber = custNumber;
this.items = items;
}
public void print(PrintStream ps) {
ps.println("*** Invoice ***");
ps.println("Customer: " + custNumber + ")");
ps.println("Our order number: " + orderNumber);
for (int i = 0; i < items.length; i++) {
Item it = items[i];
ps.println(it);
}
}
}
}
enum Media {
book, music_cd, music_vinyl, movie_vhs, movie_dvd;
}
Foreach and generic data structure
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
public class ForeachDemo {
static void iterate(Collection<String> c) {
for (String s : c)
System.out.println(s);
}
public static void main(String args[]) {
List<String> l = new ArrayList<String>();
l.add("Toronto");
l.add("Stockholm");
iterate(l);
}
}
Generic ArrayList
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.util.*;
public class ArrayListGenericDemo {
public static void main(String[] args) {
ArrayList<String> data = new ArrayList<String>();
data.add("hello");
data.add("goodbye");
// data.add(new Date()); This won"t compile!
Iterator<String> it = data.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
Generic Data Structure
import java.io.*;
interface Executor<E extends Exception> {
void execute() throws E;
}
public class GenericExceptionTest {
public static void main(String args[]) {
try {
Executor<IOException> e =
new Executor<IOException>() {
public void execute() throws IOException
{
// code here that may throw an
// IOException or a subtype of
// IOException
}
};
e.execute();
} catch(IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
}
}
}
Generic HashMap
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
import java.util.HashMap;
public class HashDemoGeneric {
public static void main(String[] args) {
HashMap<Integer,String> map = new HashMap<Integer,String>();
map.put(1, "Ian");
map.put(42, "Scott");
map.put(123, "Somebody else");
String name = map.get(42);
System.out.println(name);
}
}
Generic Stack
/*
* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
*
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/
public class MyStackDemo {
public static void main(String[] args) {
MyStack<String> ms1 = new MyStack<String>();
ms1.push("billg");
ms1.push("scottm");
while (ms1.hasNext()) {
String name = ms1.pop();
System.out.println(name);
}
// Old way of using Collections: not type safe.
MyStack ms2 = new MyStack();
ms2.push("billg"); // EXPECT WARNING
ms2.push("scottm"); // EXPECT WARNING
ms2.push(new java.util.Date()); // EXPECT WARNING
// Show that it is broken
try {
String bad = (String)ms2.pop();
System.err.println("Didn"t get expected exception!");
} catch (ClassCastException ex) {
System.out.println("Did get expected exception.");
}
// Removed the brokenness, print rest of it.
while (ms2.hasNext()) {
String name = (String)ms2.pop();
System.out.println(name);
}
}
}
/** A lax Stack implementation.
* @version $Id: MyStack.java,v 1.4 2004/03/07 23:18:59 ian Exp $
*/
class MyStack<T> {
private int ix = 0;
public static final int MAX = 10;
private T[] data = (T[])new Object[MAX];
public void push(T obj) {
data[ix++] = obj;
}
public boolean hasNext() {
return ix > 0;
}
public boolean hasRoom() {
return ix < MAX;
}
public T pop() {
if (hasNext()) {
return data[--ix];
}
throw new ArrayIndexOutOfBoundsException(-1);
}
}
Java generic: Generics and arrays.
class Gen<T extends Number> {
T ob;
T vals[];
Gen(T o, T[] nums) {
ob = o;
vals = nums;
}
}
public class GenArrays {
public static void main(String args[]) {
Integer n[] = { 1, 2, 3, 4, 5 };
Gen<Integer> iOb = new Gen<Integer>(50, n);
// Can"t create an array of type-specific generic references.
// Gen<Integer> gens[] = new Gen<Integer>[10]; // Wrong!
Gen<?> gens[] = new Gen<?>[10]; // OK
}
}
Pre generics example that uses a collection.
/*
Java 2, v5.0 (Tiger) New Features
by Herbert Schildt
ISBN: 0072258543
Publisher: McGraw-Hill/Osborne, 2004
*/
import java.util.*;
public class OldStyle {
public static void main(String args[]) {
ArrayList list = new ArrayList();
// These lines store strings, but any type of object
// can be stored. In old-style code, there is no
// convenient way restrict the type of objects stored
// in a collection
list.add("one");
list.add("two");
list.add("three");
list.add("four");
Iterator itr = list.iterator();
while(itr.hasNext()) {
// To retrieve an element, an explicit type cast is needed
// because the collection stores only Object.
String str = (String) itr.next(); // explicit cast needed here.
System.out.println(str + " is " + str.length() + " chars long.");
}
}
}
The GenStack Class
import java.util.LinkedList;
class GenStack<E> {
private LinkedList<E> list = new LinkedList<E>();
public void push(E item) {
list.addFirst(item);
}
public E pop() {
return list.poll();
}
public E peek() {
return list.peek();
}
public boolean hasItems() {
return !list.isEmpty();
}
public int size() {
return list.size();
}
}
public class GenStackTest {
public static void main(String[] args) {
GenStack<String> gs = new GenStack<String>();
gs.push("One");
gs.push("Two");
gs.push("Three");
gs.push("Four");
System.out.println("There are " + gs.size() + " items in the stack.\n");
System.out.println("The top item is: " + gs.peek() + "\n");
System.out.println("There are still " + gs.size() + " items in the stack.\n");
System.out.println("Popping everything:");
while (gs.hasItems())
System.out.println(gs.pop());
System.out.println("There are now " + gs.size() + " items in the stack.\n");
System.out.println("The top item is: " + gs.peek() + "\n");
}
}
Unchecked Example
import java.util.*;
public class UncheckedExample {
public void processIntVector(Vector<Integer> v)
{
// perform some processing on the vector
}
public static void main(String args[])
{
Vector<Integer> intVector = new Vector<Integer>();
Vector oldVector = new Vector();
UncheckedExample ue = new UncheckedExample();
// This is permitted
oldVector = intVector;
// This causes an unchecked warning
intVector = oldVector;
// This is permitted
ue.processIntVector(intVector);
// This causes an unchecked warning
ue.processIntVector(oldVector);
}
}