Accessing ArrayList<ArrayList<SomeObject>> elements - java

I have an ArrayList of ArrayLists where i need to find a simple way of accessing the elements, to make it easier to understand i have drawn my goal of what i want to achieve:
As seen on the image above the main ArrayList consists of m ArrayList, where i wish to get an element by using a get method which goes from 0 to N elements, where N is the total elements of ArrayList1 and ArrayList2. More ArrayList's may occur.
I can of course iterate through the elements by using two for-loops, which is not what im searching for in this case.

You would need to basically have the the ArrayList members on your new wrapper class and implement them in a different manner. I whipped up an example that demonstrates the correct index being calculated in get().
import java.util.ArrayList;
public class ListHolder<T> {
public ArrayList<ArrayList<T>> list = new ArrayList<ArrayList<T>>();
public int size() {
int size = 0;
for (int i = 0; i < list.size(); i++) {
size += list.get(i).size();
}
return size;
}
public T get(int i) {
if (i >= size())
return null;
int listIndex = 0;
int valueIndex = i;
while (valueIndex >= list.get(listIndex).size()) {
valueIndex -= list.get(listIndex++).size();
}
return list.get(listIndex).get(valueIndex);
}
}
What I used to verify my methods:
public static void main(String[] args)
{
ListHolder<Object> listHolder = new ListHolder<Object>();
listHolder.list.add(new ArrayList<Object>());
listHolder.list.get(0).add("hello");
listHolder.list.get(0).add("world");
listHolder.list.add(new ArrayList<Object>());
listHolder.list.get(1).add("a");
listHolder.list.get(1).add("b");
listHolder.list.get(1).add("c");
System.out.println("Size: " + listHolder.size());
System.out.println("listHolder[0]: " + listHolder.get(0)); // "hello"
System.out.println("listHolder[1]: " + listHolder.get(1)); // "world"
System.out.println("listHolder[2]: " + listHolder.get(2)); // "a"
System.out.println("listHolder[3]: " + listHolder.get(3)); // "b"
System.out.println("listHolder[4]: " + listHolder.get(4)); // "c"
System.out.println("listHolder[5]: " + listHolder.get(5)); // "null"
}

You don't provide many details about what these lists are, and if they're mutable or not. But you could probably use an additional list containing all the elements of all the sublists:
private class Generation
private List<List<Element>> populations = new ArrayList<>();
private List<Element> allElements = new ArrayList<>();
public Element getElementAt(int elementIndex) {
return allElements.get(elementIndex);
}
public void addPopulation(List<Element> population) {
populations.add(new ArrayList<>(population));
allElements.addAll(population);
}
public List<Element> getPopulationAt(int populationIndex) {
return Collections.unmodifiableList(populations.get(populationIndex));
}
}

class Plot {
class Point {
int x;
int y;
}
List<List<Point>> area = new ArrayList<List<Point>>();
Point getPoint (int x, int y) throws IndexOutOfBoundsException {
if (x < 0 && x >= area.size())
throw new IndexOutOfBoundsException();
int l = area.get(x).size();
int i = (int)y/l;
int j = y % l;
return area.get(x+i).get(j);
}
void setPoint (int x, int y, Point p) throws IndexOutOfBoundsException {
if (x < 0 && x >= area.size())
throw new IndexOutOfBoundsException();
int l = area.get(x).size();
int i = (int)y/l;
int j = y % l;
area.get(x+i).set(j, p);
}
}

Related

Null pointer exception while implementing Heapify for removing minimum value in MinHeap

For the below program:
public class MinHeap<T extends Comparable<? super T>>
implements HeapInterface<T> {
private T[] backingArray;
private int size;
// Do not add any more instance variables
/**
* Creates a Heap.
*/
public MinHeap() {
backingArray = (T[]) new Comparable[STARTING_SIZE];
size = 0;
}
#Override
public void add(T item) {
if (item == null) {
throw new IllegalArgumentException("Item was null.");
}
if (size + 1 >= backingArray.length) {
resize();
}
backingArray[size + 1] = item;
int i = size + 1;
while (i > 1 && backingArray[i].compareTo(backingArray[i / 2]) <= 0) {
swap(backingArray[i], backingArray[i / 2], i, i / 2);
i = i / 2;
}
size++;
}
private void resize() {
T[] backingArrayTemp = backingArray;
backingArray = (T[]) new Comparable[backingArrayTemp.length * 2];
for (int i = 1; i < size + 1; i++) {
backingArray[i] = backingArrayTemp[i];
}
}
private void swap(T item1, T item2, int i, int parent) {
backingArray[parent] = item1;
backingArray[i] = item2;
}
#Override
public T remove() {
if (isEmpty()) {
throw new NoSuchElementException("Heap is empty.");
}
T temp = backingArray[1];
backingArray[1] = backingArray[size + 1];
size--;
heapify(1);
return temp;
}
private void heapify(int i) {
int left = 2*i;
int right = 2*i + 1;
int min = i;
if (left < size && backingArray[left].compareTo(backingArray[min])
< 0) {
min = left;
}
if (right < size
&& backingArray[right].compareTo(backingArray[min]) < 0) {
min = right;
}
if (min != i) {
swap(backingArray[i], backingArray[min], i, min);
heapify(min);
}
}
#Override
public boolean isEmpty() {
return size == 0;
}
#Override
public int size() {
return size;
}
#Override
public void clear() {
size = 0;
backingArray = (T[]) new Comparable[STARTING_SIZE];
}
We start indexing at i = 1.
My add method works fine, and I've tried changing from backingArray[1] = backingArray[size + 1]; to backingArray[1] = backingArray[size]
in the remove method, but that doesn't seem right and also didn't work. It got rid of the null pointer but didn't pass all my tests. I'm getting null pointers at
backingArray[left].compareTo(backingArray[min]) < 0)
because backingArray[min] is null.
Stack trace
java.lang.NullPointerException
at java.lang.Integer.compareTo(Integer.java:1216)
at java.lang.Integer.compareTo(Integer.java:52)
at MinHeap.heapify(MinHeap.java:68)
at MinHeap.remove(MinHeap.java:60)
I can't really test this, right now, but I think the main problem is in the resize() method. When you create the temporary array to hold the data
T[] backingArrayTemp = backingArray;
you actually tell the new array to point to the same address in the memory as the original backingArray. Then you reallocate backingArray and also the temp array, since they point to the same place in memory. Then, of course, all the elements will not be initialized and the bеhaviour will not be as expected.
The correct way to do this is to create a "new" array and then copy the values:
T[] backingArrayTemp = new T[backingArray.length];
for(int i = 0; i < backingArray.length; ++i)
backingArrayTemp[i] = new T(backingArray[i]);
Where each element is copied with a constructor to avoid similar issues.
About heapify() - I don't know how exactly you will use that min heap, but I guess you will always put the elements one at a time. If you ever need to create the heap from a random array you will need a more complex routine that goes through the entire heap. I can provide you with some more information, if interested.
The problem was I didn't set backingArray[size] = null.

Iterating over an ArrayList adding values

Is it possible to iterate over a ArrayList adding not all instances but every 12? There are many threads on using addAll to add all instances but not sections.
I currently have an ArrayList containing hundreds of float values:
Snippet:
120.5, 22.2, 76.2, 64.5, 38.3, 27.1, 149.4, 62.3, 127.9, 79.1, 83.4, 68.3, 61.0, 83.4, 5.4, 83.8, 78.3, 111.8, 104.1, 145.2, 94.3, 20.0, 104.7, 35.9, 68.6, 10.1, 41.1, 82.2, 170.7, 17.2, 122.1, 61.0, 46.3, 101.1, 59.0, 30.0, ...
What I want to do is sum the first 12 instances and put this total in a new ArrayList, sum the next 12 instances, store this into the newly created ArrayList and so on. There are exactly 996 instances so i should have 83 new values in this new ArrayList (996/12=83).
Can this be done? If so how? Here is where I have got to...
// ArrayList that contains the float values shown above
public MonthData depthValues() {
ArrayList<Float> rValue = new ArrayList<>();
for (int i = 0; i<months.size(); i++)
{
rValue.add(months.get(i).getDepthMM());
}
System.out.println(rValue);
System.out.println(rValue.size());
return null;
}
//New arrayList im trying to make
//probably done this wrong, help needed here
public MonthData depthTotals() {
ArrayList<Float> depthAdd = new ArrayList<Float>();
int t = 12;
for(int i = 0; i<rValue.size(); ++i)
{
??????????????????
}
}
Any help will be greatly appreciated I cant seem to find anything on this anywhere as I think the sum of all instances is such a popular topic. Its probably a case of iterating properly. In regards to the summing I would have use accumulate in c++, but do not know the equivalent of this in java (if there is one). Thank you for any advice/assistance in advance!
MORE CODE:
public class WeatherStation {
private ArrayList<MonthData> months;
private ArrayList<MonthData> rValue;
private ArrayList<MonthData> depthAdd;
MonthData is a model for data being read to this class it consists on a lot of getters....
public class MonthData {
int y;
int m;
float h;
...
public MonthData(String data) throws Exception {
...
this.parseData(data);
}
void parseData(String csvData) {
String[] parseResult = csvData.trim().split("\\s+");
this.setYear(parseResult[0]);
this.setMonth(parseResult[1]);
...
public String toString() {
return "y =" + year + ", m =" + month + ",...
}
public int getY() {
return y;
}
// followed by lots of getters for: m, h, c, f, r, s, ...
public MonthData depthValues() {
ArrayList<Float> rValue = new ArrayList<>();
for (int i = 0; i<months.size(); i++)
{
rValue.add(months.get(i).getDepthMM());
}
System.out.println(rValue);
System.out.println(rValue.size());
return null;
}
Code recommended:
public MonthData depthTotals() {
ArrayList<Float> depthAdd = new ArrayList<>();
Iterator<Float> it = rValue.iterator();
final int MAX = 12;
while (it.hasNext()){
float sum = 0f;
int counter = 1;
//iterating 12 times
//still check if there is an element in list
while (counter < MAX && it.hasNext()){
sum += it.next();
counter++;
}
depthAdd.add(sum);}
}
ISSUE: Iterator<Float> it = rValue.iterator();
Type mismatch: cannot convert from Iterator<MonthData> to Iterator<Float>
The best way to do this is using Iterator and a counter of 12 by using a while. Here's an example:
List<Float> yourList = ...;
// fill yourList
List<Float> results = new ArrayList<>();
Iterator<Float> it = yourList.iterator();
final int MAX = 12;
while (it.hasNext()) {
float sum = 0f;
int counter = 1;
//iterating 12 times
//still, check if there's an element in your list
while (counter <= MAX && it.hasNext()) {
sum += it.next();
counter++;
}
result.add(sum);
}
I would recommend you use double or Double instead of float as it has around half a trillion times the accuracy.
You can sum every block of 12 like this
public static List<Double> sumBlocks(List<Double> list, int blockSize) {
List<Double> ret = new ArrayList<>();
for(int i = 0; i < list.size(); i += blockSize) {
double sum = 0;
for(int j = 0, len = Math.min(list.size() - i, blockSize); j < len; j++)
sum += list.get(i + j);
ret.add(sum);
}
return ret;
}
and call
List<Double> sums = sumBlocks(list, 12);
Just to demonstrate yet another way to accomplish this:
public static List<Double> sumBlocks(List<Double> list, int blockSize) {
List<Double> result = new ArrayList<>();
double sum = 0d;
for (int i = 0; i < list.size(); i++) {
if (i > 0 && i % blockSize == 0) {
result.add(sum);
sum = 0d;
}
sum += list.get(i);
}
result.add(sum);
return result;
}
Lista<Double> list = // original list
List<Double> ret = new ArrayList<>();
int counter = 0;
double sum = 0;
for (Double f : list) {
if (counter == 12) {
sum = 0;
counter = 0;
ret.add(sum);
}
sum += f;
counter++;
}
// if list is not a multiple of 12
if (list.size() % 12 != 0) {
ret.add(sum);
}
return ret;
try this:
public float total;
for(int i; i < rValue.Size(); i ++)
{
total += rValue[i];
if(i%12=0)
{
add total to new ArrayList
total = 0;
}
}
Arraylist objects inherit the sublist(start, end) method from the List class. You can use myList.sublist(i, j) to access the sublist and get your sum. From there, it should be just simple arithmetic to get your iteration. Inside your for-loop, it should be: myList.sublist(i*12, i*12 + 12).
//Input list
ArrayList<Float> inputList = new ArrayList<Float>();
ArrayList<Float> result = new ArrayList<Float>();
int groupSize = 12;
int offset=0;
while(offset < inputList.size()) {
int toIndex = (inputList.size()-offset)>=groupSize? offset+groupSize : inputList.size();
result.add( listSum(inputList.subList(offset, toIndex)) );
offset += groupSize;
}
Helper method to add items in a list
static float listSum(List<Float> ar) {
float accumulator = 0f;
for(float item:ar) {
accumulator += item;
}
return accumulator;
}

Sorting an array on more than one criterion

I have this method to sort an array of objects by the variable id, there's name & GPA, too. How would you go about sorting the entire array of objects? Im only getting the id's sorted but the names when outputted are mixed. This is what I have thus far.
private Student[] st;
private int count;
public ProcessStudents() {
st = new Student[5];
count = 0;
public void sortAscendingID() {
for (int n = 0; n < count - 1; n++) {
int min = st[n].getId();
int index = n;
for (int o = n + 1; o < count; o++) {
if (st[o].getId() < min) {
min = st[o].getId();
index = o;
}
}
if (st[n].getId() > min) {
int p = st[n].getId();
st[n].setId(min);
st[index].setId(p);
}
}
}
}
If I were writing code for a production system rather than say homework or whatever I'd do this:
List<Student> list = new ArrayList<Student>(Arrays.asList(st));
Collections.sort(list);
Would implement Comparable and override its method:
#Override
public int compareTo(Object arg0) {
// return -1, 0 or 1 depending on compared fields.
// if(this.GetId()>((Student)arg0).GetId())
// ...
return 0;
}
...
Collections.sort(collectionOfStudentObjects);

Collision Resolution in a HashTable

I am attempting to build my own implementation of a hash table in Java in order to gain a better grasp on how hashing works. I am using separate chaining and growing the table and rehashing everything when the load gets over 75% or I have a single chain over 20 in length. I'm hashing strings. I've tried everything I can think of but when I attempt to build the table it runs for a few seconds and then throws a StackOverflowError in my grow method.
Here is the code for the actual HashTable this include the arrayList for the actual table and some ints to keep track of the longest chain the number of collisions and the size. It also includes methods to insert, grow (rehash everything in new arrayList), hash a string, and to find a prime number higher than a given number as well the getter/setters.
import java.util.ArrayList;
import java.util.LinkedList;
public class HashTable {
private ArrayList<LinkedList<String>> hashes;
private int collisionCounter; //the total amount of collisions that have occurred
private int longest; //the length collision
private int size;
public HashTable(int size) {
this.hashes = new ArrayList<LinkedList<String>>();
for (int i = 0; i < size; i++) {
hashes.add(new LinkedList<String>());
}
this.collisionCounter = 0;
this.longest = 0;
this.size = size;
}
public int getCollisionCounter() {
return collisionCounter;
}
public int size() {
return this.size;
}
public int getLongest() {
return this.longest;
}
//grows array to a new size
public void grow(int newSize, int numElements) {
ArrayList<LinkedList<String>> oldHashes = new ArrayList<LinkedList<String>>(this.hashes);
this.hashes = new ArrayList<LinkedList<String>>();
this.collisionCounter = 0;
this.longest = 0;
this.size = newSize;
for (int i = 0; i < this.size; i++) {
hashes.add(new LinkedList<String>());
}
for (int i = 0; i < oldHashes.size(); i++) {
LinkedList<String> currentList = oldHashes.get(i);
for (int q = 0; q < currentList.size(); q++) {
this.insert(currentList.get(q));
}
}
if (this.longest > 20 || this.load(numElements) > .75) {
newSize = newSize + 20;
newSize = this.findPrime(newSize);
this.grow(newSize, numElements);
}
}
//inserts into hashtable keeps track of collisions and the longest chain
public void insert(String element) {
int index = this.hash(element);
this.hashes.get(index).add(element);
if (index < this.size) {
if (this.hashes.get(index).size() > 1) {
this.collisionCounter++;
if (this.hashes.size() > this.longest) {
this.longest++;
}
}
}
}
//finds the first prime number that is larger that the starting number or the original number if that is prime
//if used to find a new table size the int in the parameters will need to be incremented
public int findPrime(int startInt) {
int newNum = startInt++;
boolean isFound = false;
while (!isFound) {
boolean isPrime = true;
int divisor = 2;
while (isPrime && divisor < newNum / 2) {
if (newNum % divisor == 0) {
isPrime = false;
} else {
divisor++;
}
}
if (isPrime) {
isFound = true;
} else {
newNum++;
}
}
return newNum;
}
public double load(int numElements) {
return (numElements + 0.0) / (this.size + 0.0); //int division may be a problem
}
//helper method for insert and search creates hash value for a word
public int hash(String ele) {
char[] chars = ele.toCharArray();
double hashCode = 0;
for (int i = 0; i < chars.length; i++) {
hashCode += chars[i] * Math.pow(5521, chars.length - i);
}
if (hashCode < 0) {
hashCode = hashCode + this.size;
}
return (int) (hashCode % this.size);
}
//method to search for a word in hashtable finds a string in the hastable return true if found false if not found
public boolean search(String goal) {
int index = this.hash(goal);
LinkedList<String> goalList = this.hashes.get(index);
for (int i = 0; i < goalList.size(); i++) {
if (goalList.get(i).equals(goal)) {
return true;
}
}
return false;
}
}
Here is the code for the method that actually builds the table it takes an arrayList of all the words and inserts them into the array (hashing them as it goes) and checks the load/collision length and grows it if needed.
public static HashTable createHash(ArrayList<String> words) {
int initSize = findPrime(words.size());
HashTable newHash = new HashTable(initSize);
for (int i = 0; i < words.size(); i++) {
newHash.insert(words.get(i));
if (newHash.load(i) > .75 || newHash.getLongest() > 20) {
int size = newHash.size();
size = size + 25;
int newSize = findPrime(size);
newHash.grow(newSize, i);
}
}
return newHash;
}
Sorry this is a lot of code to sort through but I cannot figure out what I am doing wrong here and don't know a way to condense it down. Any help is really appreciated!
In your insert method you should have the following instead for keeping track of the longest chain
if(this.hashes.get(index).size() > this.longest) {
this.longest = this.hashes.get(index).size();
}
that explains why it runs for a few seconds and then hits a StackOverflowError, you are recursing infinitely because the value of longest isn't changing (since this.hashes.size() won't change)

Java: Expanding array size, can't seem to keep all values in original locations

For my current homework, I'm trying to sort my array through a generic class as the user inserts values into its locations. When the size reads as fully loaded, the array class calls in an expansion method that increases the size of the array while retaining its values in proper locations, which I followed from my Professor's note. For some reason, all my values except for location[0] seem to either be misplaced or erased from the array. I'm leaning that the problem originates in the expansion method but I have no idea how to fix this.
For example, the initial size is currently set to 5 but increments by 3 when expansion method is called. The user can input values 1,2,3,4,5 perfectly. But expansion is called when user inputs new value 6 that outputs an array of 1, 6, null, null, null, null. Any further will lead to the error "Exception in thread "main" java.lang.NullPointerException"
Here is my Sorted Array class:
public class SortedArray {
private int size;
private int increment;
private int top;
Comparable[] a;
public SortedArray(int initialSize, int incrementAmount)
{
top = -1;
size = initialSize;
increment = incrementAmount;
a = new Comparable [size];
}
public int appropriatePosition(Comparable value)
{
int hold = top;
if(hold == -1)
{
hold = 0;
}
else
{
for(int i = 0; i <= top; i++)
{
if(value.compareTo(a[i]) > 0)
{
hold = i + 1;
}
}
}
return hold;
}
public Comparable smallest()
{
return a[0];
}
public Comparable largest()
{
return a[top];
}
public void insert(Comparable value)// the method that my driver calls for.
{
int ap = appropriatePosition(value);
//Expansion if full
if(full() == true)
{
expansion();
}
//Shifting numbers to top
for(int i = top; i >= ap ; i--)
{
{
a[i + 1] = a[i];
}
}
a[ap] = value;
top++;
}
public boolean full()
{
if(top == a.length -1)
{
return true;
}
else
{
return false;
}
}
public void expansion()//here's where the expansion begins
{
int newSize = a.length + increment;
Comparable[] tempArray = new Comparable[newSize];
for(int i= 0; i < a.length; i++)
{
tempArray[i]= a[i];
a = tempArray;
}
}
Here's my driver class that calls for the insert method in SortedArray class.
public class IntDriver {
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
//Creating variables
int data;
boolean check = false;
int choice;
int size = 5;
int increment = 3;
SortedArray b = new SortedArray(size, increment);
//Creating Menu
System.out.println("Please choose through options 1-6.");
System.out.println("1. Insert\n2. Delete\n3. Clear\n4. Smallest\n5. Largest\n6. Exit\n7.Redisplay Menu");
while(check == false)
{
choice = keyboard.nextInt();
switch(choice)
{
case 1:
System.out.println("Type the int data to store in array location.");
data = keyboard.nextInt();
Integer insertObj = new Integer(data);
b.insert(insertObj);
System.out.println("The value " + data + " is inserted");
b.print();
break;
In the expansion method, you're replacing a too soon. The replacement should happen after the for loop:
public void expansion()//here's where the expansion begins
{
int newSize = a.length + increment;
Comparable[] tempArray = new Comparable[newSize];
for(int i= 0; i < a.length; i++)
{
tempArray[i]= a[i];
}
a = tempArray;
}

Categories