Collections Data Structure Java

/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Serializable;
/**
 * A simple class that implements a growable array of ints, and knows how to
 * serialize itself as efficiently as a non-growable array.
 */
public class IntList implements Serializable {
  protected int[] data = new int[8]; // An array to store the numbers.
  protected transient int size = 0; // Index of next unused element of array
  /** Return an element of the array */
  public int get(int index) throws ArrayIndexOutOfBoundsException {
    if (index >= size)
      throw new ArrayIndexOutOfBoundsException(index);
    else
      return data[index];
  }
  /** Add an int to the array, growing the array if necessary */
  public void add(int x) {
    if (data.length == size)
      resize(data.length * 2); // Grow array if needed.
    data[size++] = x; // Store the int in it.
  }
  /** An internal method to change the allocated size of the array */
  protected void resize(int newsize) {
    int[] newdata = new int[newsize]; // Create a new array
    System.arraycopy(data, 0, newdata, 0, size); // Copy array elements.
    data = newdata; // Replace old array
  }
  /** Get rid of unused array elements before serializing the array */
  private void writeObject(ObjectOutputStream out) throws IOException {
    if (data.length > size)
      resize(size); // Compact the array.
    out.defaultWriteObject(); // Then write it out normally.
  }
  /** Compute the transient size field after deserializing the array */
  private void readObject(ObjectInputStream in) throws IOException,
      ClassNotFoundException {
    in.defaultReadObject(); // Read the array normally.
    size = data.length; // Restore the transient field.
  }
  /**
   * Does this object contain the same values as the object o? We override
   * this Object method so we can test the class.
   */
  public boolean equals(Object o) {
    if (!(o instanceof IntList))
      return false;
    IntList that = (IntList) o;
    if (this.size != that.size)
      return false;
    for (int i = 0; i < this.size; i++)
      if (this.data[i] != that.data[i])
        return false;
    return true;
  }
  /** A main() method to prove that it works */
  public static void main(String[] args) throws Exception {
    IntList list = new IntList();
    for (int i = 0; i < 100; i++)
      list.add((int) (Math.random() * 40000));
    IntList copy = (IntList) Serializer.deepclone(list);
    if (list.equals(copy))
      System.out.println("equal copies");
    Serializer.store(list, new File("intlist.ser"));
  }
}
/*
 * Copyright (c) 2000 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 2nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book (recommended),
 * visit http://www.davidflanagan.com/javaexamples2.
 */
/**
 * This class defines utility routines that use Java serialization.
 */
class Serializer {
  /**
   * Serialize the object o (and any Serializable objects it refers to) and
   * store its serialized state in File f.
   */
  static void store(Serializable o, File f) throws IOException {
    ObjectOutputStream out = // The class for serialization
    new ObjectOutputStream(new FileOutputStream(f));
    out.writeObject(o); // This method serializes an object graph
    out.close();
  }
  /**
   * Deserialize the contents of File f and return the resulting object
   */
  static Object load(File f) throws IOException, ClassNotFoundException {
    ObjectInputStream in = // The class for de-serialization
    new ObjectInputStream(new FileInputStream(f));
    return in.readObject(); // This method deserializes an object graph
  }
  /**
   * Use object serialization to make a "deep clone" of the object o. This
   * method serializes o and all objects it refers to, and then deserializes
   * that graph of objects, which means that everything is copied. This
   * differs from the clone() method of an object which is usually implemented
   * to produce a "shallow" clone that copies references to other objects,
   * instead of copying all referenced objects.
   */
  static Object deepclone(final Serializable o) throws IOException,
      ClassNotFoundException {
    // Create a connected pair of "piped" streams.
    // We'll write bytes to one, and them from the other one.
    final PipedOutputStream pipeout = new PipedOutputStream();
    PipedInputStream pipein = new PipedInputStream(pipeout);
    // Now define an independent thread to serialize the object and write
    // its bytes to the PipedOutputStream
    Thread writer = new Thread() {
      public void run() {
        ObjectOutputStream out = null;
        try {
          out = new ObjectOutputStream(pipeout);
          out.writeObject(o);
        } catch (IOException e) {
        } finally {
          try {
            out.close();
          } catch (Exception e) {
          }
        }
      }
    };
    writer.start(); // Make the thread start serializing and writing
    // Meanwhile, in this thread, read and deserialize from the piped
    // input stream. The resulting object is a deep clone of the original.
    ObjectInputStream in = new ObjectInputStream(pipein);
    return in.readObject();
  }
  /**
   * This is a simple serializable data structure that we use below for
   * testing the methods above
   */
  public static class DataStructure implements Serializable {
    String message;
    int[] data;
    DataStructure other;
    public String toString() {
      String s = message;
      for (int i = 0; i < data.length; i++)
        s += " " + data[i];
      if (other != null)
        s += "\n\t" + other.toString();
      return s;
    }
  }
  /** This class defines a main() method for testing */
  public static class Test {
    public static void main(String[] args) throws IOException,
        ClassNotFoundException {
      // Create a simple object graph
      DataStructure ds = new DataStructure();
      ds.message = "hello world";
      ds.data = new int[] { 1, 2, 3, 4 };
      ds.other = new DataStructure();
      ds.other.message = "nested structure";
      ds.other.data = new int[] { 9, 8, 7 };
      // Display the original object graph
      System.out.println("Original data structure: " + ds);
      // Output it to a file
      File f = new File("datastructure.ser");
      System.out.println("Storing to a file...");
      Serializer.store(ds, f);
      // Read it back from the file, and display it again
      ds = (DataStructure) Serializer.load(f);
      System.out.println("Read from the file: " + ds);
      // Create a deep clone and display that. After making the copy
      // modify the original to prove that the clone is "deep".
      DataStructure ds2 = (DataStructure) Serializer.deepclone(ds);
      ds.other.message = null;
      ds.other.data = null; // Change original
      System.out.println("Deep clone: " + ds2);
    }
  }
}