I am trying to write an ADT for a class that incorporates a sequence when there is a small amount of data to store (<1000 key values) and uses a HashTable otherwise. I have to write the sequence class myself but i was delighted to find out that java has it's own built in HashTable class. However, one of the requirements for this ADT is that it must be able to display the previous and next keys (called VINs in the code). I can do this easily with my sequence class, however I was wondering if the built in HashTable class had such a function. Will I have to write my own HashTable class or is there a way I can achieve my goal without having to do so? Thank you all for your help in advance, I really appreciate it!
This is the CVR class (data is passed to this class and it calls upon the sequence or HastTable class)
import java.util.*;
public class CVR
{
//this will be used to generate random alpha numeric numbers
private final static String alphaNumeric="ABDCEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//key
private String VIN;
//threshold (determines which ADT to use)
private int threshold;
//length of key
private int VINLength;
//this is an object of Archive which will hold the data associated with VIN
private Account value;
//TBD
//private Collection<Account> activeVINS;
//HashMap to store all the key-value pairs
//the value come in the form of a stack because,
//multiple events can be associated with the same
//VIN, and must be shown in reverse-chronological order
private Hashtable<String, Stack<Account>> hashRecords;
private sequence seqRecords;
//This will keep track of all VINs and make sure
//none of them are repeated
private HashSet<String> VINRecorder;
private boolean hashTabl=false;
//default constructor
public CVR(int threshold) throws Exception
{
this.setThreshold(threshold);
if (threshold>1000)
{
hashRecords=new Hashtable<>();
hashTabl=true;
}
else
{
seqRecords=new sequence();
hashTabl=false;
}
}
//not sure this is even needed
//parameterized constructor for CVR, takes VIN
//and adds it to VINRecorder
//re-evaluate this method, with this a VIN is added to HashSet, but not to
//HashMap. At the same time I'm not sure We want VINs w/o associated accounts
//to be in HashMap. TBD
//For now actually, I will add them to HashMap, this may change down the line...
/**
public CVR (String VIN) throws Exception
{
this.VIN=VIN;
records=new Hashtable<>();
VINRecorder=new HashSet<>();
add(VIN, null);
//Stack<Account> stack = new Stack<Account>();
//VINRecorder.add(VIN);
}
**/
//accessors and mutators
//VIN getters and setters
public String getVIN()
{
return VIN;
}
public void setVIN(String VIN)
{
this.VIN=VIN;
VINRecorder=new HashSet<>();
VINRecorder.add(VIN);
}
//threshold getters and setters
public int getThreshold()
{
return threshold;
}
//for this one we have to keep in mind the restriction set
//on us in the instructions
public void setThreshold(int threshold) throws Exception
{
if(threshold<100 || threshold>900000)
{
//System.out.println("Invalid input for threshold");
throw new Exception("Invalid input for threshold");
}
else
{
this.threshold=threshold;
}
}
//VINLength getters and setters
public int getVINLength()
{
return VINLength;
}
//again for this one. we need to take the
//instructions into account for this special
//case
public void setVINLength(int VINLength) throws Exception
{
if(VINLength<10 || VINLength>17)
{
throw new Exception("Invalid input for VIN length");
}
else
{
this.VINLength=VINLength;
}
}
//Now onto the methods
//Generate method
//This method should randomly generate a sequence
//containing n new non-existing valid keys
//***Must determine whether the output is a sequence or not
public String generate(int size) throws Exception
{
char[] Arr= alphaNumeric.toCharArray();
String[] ender=new String[size];
//generating random number between 10 and 17
Random r= new Random();
int low=10;
int high=17;
for(int x=0; x<size;x++)
{
int highLow=r.nextInt(high-low)+10;
StringBuilder newString=new StringBuilder();
//making string between length of 10 and 17 randomly
for(int i=0; i<highLow; i++)
{
newString.append(Arr[new Random().nextInt(Arr.length)]);
}
///////////////////
String newVIN=newString.toString();
//System.out.println(newVIN);
//This must be further explored, I do not know why,
//but for some reason it does not work if the first
//condition is not there, to be explored
if(newVIN!=null)
{
}
//stops here for some reason, must find out why, something is wrong with this statement
else if(VINRecorder.contains(newVIN))
{
x--;
}
else
{
ender[x]=newString.toString();
}
ender[x]=newString.toString();
}
//System.out.println("hello");
System.out.println(Arrays.toString(ender));
return Arrays.toString(ender);
}
//method allKeys
//this method should return all keys as a sorted
//sequence in lexicographic order
//the plan here is to use
/**
public LinkedList<Account> allKeys()
{
}
**/
//add method
//****must check to see if must be resized later
public void add(String VIN, Account value) throws Exception
{
if(hashTabl==true)
{
if(!VIN.equals(value.getVIN()))
{
System.out.println("Something went wrong :/");
throw new Exception("VIN does not match account");
}
else if(hashRecords.containsKey(VIN))
{
System.out.println("VIN exists, adding to record");
hashRecords.get(VIN).add(value);
System.out.println("Success!");
}
else
{
System.out.println("New account made, record added!");
Stack<Account> stack = new Stack<Account>();
stack.add(value);
hashRecords.put(VIN, stack);
System.out.println("Success!");
//resize here
//
}
}
else
{
if(value==null)
{
Account saveVIN=new Account(VIN);
seqRecords.add(saveVIN);
}
seqRecords.add(value);
}
}
//remove method
//***must check to see if must be resized later
public void remove(String VIN)
{
if(hashTabl==true)
{
if(hashRecords.containsKey(VIN))
{
hashRecords.remove(VIN);
//resize here
//
}
else
{
System.out.println("Key does not exist in HashTable");
}
}
else
{
seqRecords.removeVIN(VIN);
}
}
//getValues method
public Stack<Account> getValues(String VIN)
{
if(hashTabl == true)
{
if(hashRecords.containsKey(VIN))
{
Stack<Account> values = new Stack<Account>();
values=hashRecords.get(VIN);
return values;
}
else
{
System.out.println("This VIN could not be found in directory");
return null;
}
}
else
{
return seqRecords.getAccount(VIN);
}
}
//nextKey methods
public String nextVIN(String VIN)
{
//unfinished, not sure what to call here
if(hashTabl=true)
{
return hashRecords.
}
else
{
return seqRecords.nextVIN(VIN);
}
}
//previous Accidents method
public Stack<Account> prevAccids(String VIN)
{
if(hashTabl == true)
{
if(hashRecords.contains(VIN))
{
Stack<String> Accids= new Stack<String>();
Stack<Account> temp; //= new Stack<Account>();
temp=hashRecords.get(VIN);
return temp;
/**
String tempString;
while(!temp.isEmpty())
{
tempString=temp.pop().getAccids();
Accids.push(tempString);
}
temp=null;
return Accids;
**/
}
return null;
}
else
{
Stack<Account> temp;
temp=seqRecords.getAccount(VIN);
if(temp==null || temp.isEmpty())
{
System.out.println("This VIN does not exist in the sequence");
return null;
}
else
{
return temp;
}
}
}
//driver method
public static void main(String[] args) throws Exception
{
CVR hello= new CVR(100);
try
{
//System.out.println("hello");
//hello.generate(5);
Account abdcg=new Account("adsj4jandnj4", "Muhammad Ferreira", "perfect record");
Account abdcg1=new Account("adsj4jandnj4","Myriam Ferreira", "Fender Bender");
Account abdcg2= new Account("adsj4jandnj4", null, null);
/////
hello.add("adsj4jandnj4", abdcg);
hello.add("adsj4jandnj4", abdcg2);
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This is my sequence class
import java.util.ArrayList;
import java.util.Stack;
public class sequence
{
private class position
{
private Stack<Account> stack;
private int index;
//constructors
public position()
{
this.stack=new Stack<Account>();
this.index=0;
}
public position(int index, Account acc)
{
this.index=index;
this.stack=new Stack<Account>();
stack.push(acc);
}
//muatators
public int getIndex()
{
return index;
}
public void setIndex(int index)
{
this.index=index;
}
public Stack<Account> getStack()
{
return stack;
}
public void setStack(Stack<Account> newStack)
{
this.stack=newStack;
}
}
private int size;
//private int tail;
private int elementsNum;
//private int currentIndex;
private ArrayList<position> Arr;
public sequence()
{
//currentIndex=0;
size=0;
Arr= new ArrayList<position>(); ;
}
//add first method
public void add(Account account)
{
for(int i=0; i<size; i++)
{
//if already in array, push into its stack
if((Arr.get(i).getStack().peek().getVIN()).equals(account.getVIN()))
{
Arr.get(i).getStack().push(account);
break;
}
//if not in array, make new entry for it
else if(!(Arr.get(i).getStack().peek().getVIN()).equals(account.getVIN()) && i==size-1)
{
position added=new position(size, account);
Arr.add(added);
//currentIndex++;
size++;
}
}
}
//addIndex
//don't think this method is necessary for assignment
/**
public void addIndex(int ind, Account account)
{
position added=new position(ind, account);
Arr.add(ind, added);
size++;
//update indexes of position node
updateIndex();
}
*/
//resizeArray and updates index
public void resize()
{
Arr.trimToSize();
updateIndex();
}
//remove method
public void removeVIN(String VIN)
{
for (int i=0; i<size; i++)
{
if(size==0 || (!VIN.equals(Arr.get(i).getStack().peek().getVIN()) && i==size-1))
{
System.out.println("The Sequence does not contain this VIN");
break;
}
else if(VIN.equals(Arr.get(i).getStack().peek().getVIN()))
{
Arr.remove(i);
resize();
size--;
System.out.println("Successfully removed " +VIN+" and associated values");
}
}
}
//update indexes
public void updateIndex()
{
for (int i=0; i<size; i++)
{
if(Arr.get(i).getIndex() != i)
{
Arr.get(i).setIndex(i);
}
}
}
//Get Values
//Will be used in CVR for both the getValues method (return all values)
//and prevAccids method (return only the accidents not entire account)
public Stack<Account> getAccount(String VIN)
{
for (int i=0; i<size; i++)
{
if(size==0)
{
System.out.println("The Sequence is empty");
break;
}
else if(VIN.equals(Arr.get(i).getStack().peek().getVIN()))
{
return Arr.get(i).getStack();
}
}
return null;
}
//get previous VIN method
public String preVIN(String VIN)
{
for (int i=0; i<size; i++)
{
if((Arr.get(i).getStack().peek().getVIN()).equals(VIN))
{
if(i==0)
{
return "There is no previous VIN, this is the first one";
}
return Arr.get(i-1).getStack().peek().getVIN();
}
}
return null;
}
//get next VIN method
public String nextVIN(String VIN)
{
for (int i=0; i<size; i++)
{
if((Arr.get(i).getStack().peek().getVIN()).equals(VIN))
{
if(i==size-1)
{
return "There is no next VIN, this is the last one";
}
return Arr.get(i+1).getStack().peek().getVIN();
}
}
return null;
}
}
Finally, this is my Account class
//this method is similar to a node, contains
//VIN, Owner, Accidents details
public class Account
{
private String VIN;
private String owner;
private String accidents;
public Account() {};
public Account(String VIN)
{
this.VIN=VIN;
this.owner=null;
this.accidents=null;
}
public Account(String VIN, String owner, String accidents)
{
this.VIN=VIN;
this.owner=owner;
this.accidents=accidents;
}
//mutators
public void setVIN(String VIN)
{
this.VIN=VIN;
}
public String getVIN()
{
return VIN;
}
public void setOwner(String owner)
{
this.owner=owner;
}
public String getOwner()
{
return owner;
}
public void setAccids(String accidents)
{
this.accidents=accidents;
}
public String getAccids()
{
return accidents;
}
}
You may want to use TreeMap
instead of obsolete Hashtable - it is sorted by key by design and provides methods to get sequence of keys and related values:
K firstKey()
K lastKey()
K higherKey(K key)
K lowerKey(K key)
etc.