Collections Data Structure Java

/*
   This program is a part of the companion code for Core Java 8th ed.
   (http://horstmann.com/corejava)
   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 3 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.
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see .
*/
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.util.Arrays;
import java.util.Comparator;
import java.util.concurrent.Semaphore;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
 * This program animates a sort algorithm.
 * @version 1.01 2007-05-18
 * @author Cay Horstmann
 */
public class AlgorithmAnimation
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(new Runnable()
         {
            public void run()
            {
               JFrame frame = new AnimationFrame();
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
               frame.setVisible(true);
            }
         });
   }
}
/**
 * This frame shows the array as it is sorted, together with buttons to single-step the animation or
 * to run it without interruption.
 */
class AnimationFrame extends JFrame
{
   public AnimationFrame()
   {
      ArrayComponent comp = new ArrayComponent();
      add(comp, BorderLayout.CENTER);
      final Sorter sorter = new Sorter(comp);
      JButton runButton = new JButton("Run");
      runButton.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               sorter.setRun();
            }
         });
      JButton stepButton = new JButton("Step");
      stepButton.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               sorter.setStep();
            }
         });
      JPanel buttons = new JPanel();
      buttons.add(runButton);
      buttons.add(stepButton);
      add(buttons, BorderLayout.NORTH);
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
      Thread t = new Thread(sorter);
      t.start();
   }
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 300;
}
/**
 * This runnable executes a sort algorithm. When two elements are compared, the algorithm pauses and
 * updates a component.
 */
class Sorter implements Runnable
{
   /**
    * Constructs a Sorter.
    * @param values the array to be sorted
    * @param comp the component on which to display the sorting progress
    */
   public Sorter(ArrayComponent comp)
   {
      values = new Double[VALUES_LENGTH];
      for (int i = 0; i < values.length; i++)
         values[i] = new Double(Math.random());
      this.component = comp;
      this.gate = new Semaphore(1);
      this.run = false;
   }
   /**
    * Sets the sorter to "run" mode. Called on the event dispatch thread.
    */
   public void setRun()
   {
      run = true;
      gate.release();
   }
   /**
    * Sets the sorter to "step" mode. Called on the event dispatch thread.
    */
   public void setStep()
   {
      run = false;
      gate.release();
   }
   public void run()
   {
      Comparator comp = new Comparator()
         {
            public int compare(Double i1, Double i2)
            {
               component.setValues(values, i1, i2);
               try
               {
                  if (run) Thread.sleep(DELAY);
                  else gate.acquire();
               }
               catch (InterruptedException exception)
               {
                  Thread.currentThread().interrupt();
               }
               return i1.compareTo(i2);
            }
         };
      Arrays.sort(values, comp);
      component.setValues(values, null, null);
   }
   private Double[] values;
   private ArrayComponent component;
   private Semaphore gate;
   private static final int DELAY = 100;
   private volatile boolean run;
   private static final int VALUES_LENGTH = 30;
}
/**
 * This component draws an array and marks two elements in the array.
 */
class ArrayComponent extends JComponent
{
   /**
    * Sets the values to be painted. Called on the sorter thread.
    * @param values the array of values to display
    * @param marked1 the first marked element
    * @param marked2 the second marked element
    */
   public synchronized void setValues(Double[] values, Double marked1, Double marked2)
   {
      this.values = values.clone();
      this.marked1 = marked1;
      this.marked2 = marked2;
      repaint();
   }
   public synchronized void paintComponent(Graphics g) // Called on the event dispatch thread
   {
      if (values == null) return;
      Graphics2D g2 = (Graphics2D) g;
      int width = getWidth() / values.length;
      for (int i = 0; i < values.length; i++)
      {
         double height = values[i] * getHeight();
         Rectangle2D bar = new Rectangle2D.Double(width * i, 0, width, height);
         if (values[i] == marked1 || values[i] == marked2) g2.fill(bar);
         else g2.draw(bar);
      }
   }
   private Double marked1;
   private Double marked2;
   private Double[] values;
}