I am having a problem with one of my methods in my program. The method is designed to take 2 arraylists and the perform multiplication between the two like a polynomial.
For example, if I was to say list1={3,2,1} and list2={5,6,7}; I am trying to get a return value of 15,28,38,20,7. However, all I can get is an error message that says:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0.
I have provided the method below:
private static ArrayList<Integer> multiply(ArrayList<Integer> list1,ArrayList<Integer> list2) {
ArrayList<Integer> array =new ArrayList<Integer>(list1.size()+list2.size());
for (int i=0;i<array.size();i++)
array.add(i, 0);
for (int i = 0; i < list1.size(); i++)
for (int j = 0; j < list2.size(); j++)
array.set(i+j, ((list1.get(i) * list2.get(j))+array.get(i+j)));
return array;
}
Any help with solving this problem is greatly appreciated.
Change your first for loop to:
for (int i = 0 ; i < list1.size() + list2.size() ; i++)
array.add(0);
As you have it, array.size() is initially 0 so that first for loop is never even entered, so nothing is being added to array. An ArrayList's capacity is not the same thing as its size.
You may want to check there exist an element at (i+j) before you sum it up with. So do this
int elementAtLoc = 0;
if(array.size() > i+j && array.get(i+j) != null ){
elementAtLoc = array.get(i+j);
}
array.set(i+j, ((list1.get(i) * list2.get(j))+elementAtLoc));
And there is no need of this:
for (int i=0;i<array.size();i++)
array.add(i, 0);
Since we are taking care of setting 0 in the second loop itself. It saves you extra work of looping just to add zeros.
Take a look at these codes :
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer.
*/
private transient Object[] elementData;
/**
* The size of the ArrayList (the number of elements it contains).
*
* #serial
*/
private int size;
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
public int size() {
return size;
}
At this time, you have to create an instance by constructor they do not have assign the variable "size" where it contains the number of actual elements. That's reason why you get this exception.
Related
So, I am trying to create 2 randomly generated arrays,(a, and b, each with 10 unique whole numbers from 0 to 20), and then creating 2 arrays with the info of the last two. One containing the numbers that appear in both a and b, and another with the numbers that are unique to a and to b. The arrays must be listed in a "a -> [1, 2, 3,...]" format. At the moment I only know how to generate the 2 arrays, and am currently at the Intersection part. The problem is, that I can create a array with the correct list of numbers, but it will have the same length of the other two, and the spaces where it shouldn't have anything, it will be filled with 0s when its supposed to create a smaller array with only the right numbers.
package tps.tp1.pack2Arrays;
public class P02ArraysExtractUniqsAndReps {
public static void main(String[] args) {
int nbr = 10;
int min = 0;
int max = 20;
generateArray(nbr, min, max);
System.out.println();
}
public static int[] generateArray(int nbr, int min, int max) {
int[] a = new int[nbr];
int[] b = new int[nbr];
int[] s = new int[nbr];
s[0] = 0;
for (int i = 0; i < a.length; i++) {
a[i] = (int) (Math.random() * (max - min));
b[i] = (int) (Math.random() * (max - min));
for (int j = 0; j < i; j++) {
if (a[i] == a[j]) {
i--;
}
if (b[i] == b[j]) {
i--;
}
}
}
System.out.println("a - > " + Arrays.toString(a));
System.out.println("b - > " + Arrays.toString(b));
for (int k = 0; k < a.length; k++) {
for (int l = 0; l < b.length; l++) {
if (a[k] == b[l]) {
s[l] = b[l];
}else {
}
}
}
System.out.println("(a ∪ (b/(a ∩ b)) - > " + Arrays.toString(s));
return null;
}
public static boolean hasValue(int[] array, int value) {
for (int i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
}
Is there any way to create the array without the incorrect 0s? (I say incorrect because it is possible to have 0 in both a and b).
Any help/clarification is appreciated.
First, allocate an array large enough to hold the intersection. It needs to be no bigger that the smaller of the source arrays.
When you add a value to the intersection array, always add it starting at the beginning of the array. Use a counter to update the next position. This also allows the value 0 to be a valid value.
Then when finished. use Array.copyOf() to copy only the first part of the array to itself, thus removing the empty (unfilled 0 value) spaces. This works as follow assuming count is the index you have been using to add to the array: Assume count = 3
int[] inter = {1,2,3,0,0,0,0};
inter = Arrays.copyOf(inter, count);
System.out.println(Arrays.toString(inter);
prints
[1,2,3]
Here is an approach using a List
int[] b = {4,3,1,2,5,0,2};
int [] a = {3,5,2,3,7,8,2,0,9,10};
Add one of the arrays to the list.
List<Integer> list = new ArrayList<>();
for(int i : a) {
list.add(i);
}
Allocate the intersection array with count used as the next location. It doesn't matter which array's length you use.
int count = 0;
int [] intersection = new int[a.length];
Now simply iterate thru the other array.
if the list contains the value, add it to the intersection array.
then remove it from the list and increment count. NOTE - The removed value must be converted to an Integer object, otherwise, if a simple int value, it would be interpreted as an index and the value at that index would be removed and not the actual value itself (or an Exception might be thrown).
once finished the intersection array will have the values and probably unseen zeroes at the end.
for(int i = 0; i < b.length; i++) {
int val = b[i];
if (list.contains(val)) {
intersection[count++] = val;
list.remove(Integer.valueOf(val));
}
}
To shorten the array, use the copy method mentioned above.
intersection = Arrays.copyOf(intersection, count);
System.out.println(Arrays.toString(intersection));
prints
[3, 2, 5, 0, 2]
Note that it does not matter which array is which. If you reverse the arrays for a and b above, the same intersection will result, albeit in a different order.
The first thing I notice is that you are declaring your intersection array at the top of the method.
int[] s = new int[nbr];
You are declaring the same amount of space for the array regardless of the amount you actually use.
Method Arrays.toString(int []) will print any uninitialized slots in the array as "0"
There are several different approaches you can take here:
You can delay initializing the array until you have determined the size of the set you are dealing with.
You can transfer your content into another well sized array after figuring out your result set.
You could forego using Array.toString, and build the string up yourself.
My Selection Sort algorithm is not working.
I am getting the following errors:
//Exception in thread "main" java.lang.NullPointerException
Note: this is for a java class. I do not have a lot of experience. I am done with the assignment. I am trying to understand the reason why my sorting algorithm isn't working.
Any suggestions on how to correct the problem? Tips?
Corrections? ... any help at all will be appreciated.
Here is my code:
private void sortFlowers(String flowerPack[]) {
// TODO: Sort the flowers in the pack (No need to display them here) - Use Selection or Insertion sorts
// NOTE: Special care is needed when dealing with strings! research the compareTo() method with strings
for(int i = 0; i < flowerPack.length; i++){
String currentMinFlow = flowerPack[i];
int minIndex = i;
for(int j = i; j < flowerPack.length; j++){
if(currentMinFlow.compareToIgnoreCase(flowerPack[j]) <0){
currentMinFlow = flowerPack[j];
minIndex = j;
}
}
if(minIndex != i){
flowerPack[minIndex] = flowerPack[i];
flowerPack[i] = currentMinFlow;
}
}
}
Exception:
Exception in thread "main" java.lang.NullPointerException at
java.lang.String$CaseInsensitiveComparator.compare(String.java:1181) at
java.lang.String$CaseInsensitiveComparator.compare(String.java:1174) at
java.lang.String.compareToIgnoreCase(String.java:1227) at
Assignment01Driver.sortFlowers(Assignment01Driver.java:112) at
Assignment01Driver.<init>(Assignment01Driver.java:37) at
Assignment01Driver.main(Assignment01Driver.java:5)
The issue is coming from the fact that your array was created with a fixed size.
String[] flowerPack = new String[25];
When you create an array of reference type variables, each variable will be initialized with a value of null. If you call the sortFlowers method before each variable is given a value, you run into an issue.
for(int i = 0; i < flowerPack.length; i++){
String currentMinFlow = flowerPack[i];
In the above segment, you are iterating through all 25 positions in the array, including the values that still have a value of null. Then, the following line causes the error:
if(currentMinFlow.compareToIgnoreCase(flowerPack[j]) <0){
Since you are iterating through the entire array, you end up with values of currentMinFlow that are null. If you try to make a method call on a null reference value, you end up with a NullPointerException.
Generally, you rarely want to use fixed size arrays when you're unsure of how many data items you're likely to have. In this case, you would want to use an ArrayList in place of a standard array. An ArrayList is essentially a dynamic array that grows and shrinks as necessary to contain the elements you store in it. This will get rid of your problem with null values, since this will prevent you from having any unused elements in your array.
Replace
String[] flowerPack = new String[25];
with
ArrayList<String> flowerPack = new ArrayList<>();
If you wanted to add or remove a value from the ArrayList you could do
// Add value.
flowerPack.add(value);
// Remove value
flowerPack.remove(value);
If you want to access a certain element in the ArrayList:
String element = flowerPack.get(indexOfElement);
If you want to get the size of the ArrayList:
int size = flowerPack.size();
And if you don't want to modify your sorting method, you can keep it the same by replacing the line
sortFlowers(flowerPack);
with
sortFlowers(flowerPack.toArray(new String[0]));
For an overview of other ArrayList methods and properties, check the online documentation:
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html
The error says that you are trying to deal with the array that holds a value of null. to understand better, fill in all 25 spots in the array and run the program, it will not give you any error.
Here is the solution that you need.
private void sortFlowers(String flowerPack[])
{
//get the length of the array by counting arrays where the value is not null.
int length = 0;
for (int i = 0; i < flowerPack.length; i++)
{
if (flowerPack[i] != null)
{
length = length + 1;
}
}
//just confirm that the count is correct.
System.out.println(length);
//set the length to the "length" variable as we have found above.
for(int i = 0; i < length; i++)
{
String currentMinFlow = flowerPack[i];
int minIndex = i;
for(int j = i; j < length;j++){
if(currentMinFlow.compareToIgnoreCase(flowerPack[j]) <0)
{
currentMinFlow = flowerPack[j];
minIndex = j;
}
}
if(minIndex != i){
flowerPack[minIndex] = flowerPack[i];
flowerPack[i] = currentMinFlow;
}
}
}
Just replace your sortFlowers method with above code and check.
How to count duplicates in ArrayList and count only once.
Here is what I have so far:
/**
* Gets the number of duplicates in the list.
* Get the next word. It is at index i. Does it match any of the words with index > i?)
* #return the number of duplicate words in the list
*/
public int countDuplicates() {
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i; j < list.size(); j++) {
if (list.get(i).equals(j)) duplicates++;
}
}
return duplicates;
}
Here is check output:
Actual: 0
Expected: 3
I am missing something very easy. However, couldn't find what exactly it is.
How to solve this trouble?
You don't get the jth element you just compare to j directly. And as a commenter points out, j should start at i+1 to avoid comparing an element to itself. Therefore, you need to write
public int countDuplicates()
{
int duplicates = 0;
for (int i = 0; i < list.size(); i++) {
for (int j = i+1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Should be:
public int countDuplicates()
{
int duplicates = 0;
// TODO: Write the code to get the number of duplicates in the list
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
if (list.get(i).equals(list.get(j))) duplicates++;
}
}
return duplicates;
}
Use two sets for this:
final Set<X> set = new HashSet<>();
final Set<X> dups = new HashSet<>();
int dupCount = 0;
for (final X x: list) {
if (set.add(x)) // first time the element is seen
continue;
// Dup; see whether it is the first time we see it
if (dups.add(x))
dupCount++;
}
return dupCount;
This relies on the fact that Set's .add() returns true if and only if the set has been modified as the result of the operation. And note that it traverses the list only once.
I can see three problems with your current code:
You are not comparing pairs of elements. You are actually comparing an element with an index.
Your inner loop is comparing element i and element i ... and that would result in a false "duplicate" count.
If you have more than 2 copies of any given element, then you will get too many duplicate counts. (To see why, try to "hand execute" with a list of (say) three identical elements.
In fact, you have to EITHER use an auxiliary data structure (e.g. 2 Sets or a Map) OR modify the input list to avoid counting duplicates more than once.
I would note that your statement of the problem is ambiguous. "... only count each duplicate once" could mean that '[1, 1, 1]' gives either 1 or 2. It depends whether you consider each individual 1 to be a duplicate to be counted once or that we have 1 as one of a set of duplicates ... that must only be counted once.
You are comparing index j value instead of value of list list.get(j).
Do
if (list.get(i).equals(list.get(j)))
instead of
if (list.get(i).equals(j))
Consider the operation removeAll, which removes all occurrences of element from a list.
The method returns the number of elements removed.
public int removeAll(E element)
Implement this operation for:
1. Array-based unsorted list
we cant use sets.
What i have started for now:
public int removeAll(T element) {
int duplicatesRemoved = 0;
for (int i = 0; i <= array.length - 1; i++) {
for (int j = i + 1; j <= array.length - 1; j++) {
if (array[i] == array[j]) {
}
}
I'm unable to get the rest done, any help please?
Dump the contents in a collection of some sort since you're not allowed to use Set, then pull out what's in the collection.
Arrays (the class, not primitive arrays) support a contains method, but you'll be iterating over the new collection everytime, making it inefficient.
Or if you can't use Array either, you can do it in a primitive array, just walking through looking for duplicates, over and over.
I suggest that you set the duplicate elements to something like null. After you've removed all duplicates, compact the array by swapping non-null elements at the end with the null elements in the middle.
Alternatively, create an empty array, and move non-duplicate elements to the new array.
Short answer
Use a Map.
More answer
Here is an algorithm, it is functional, but can be improved:
Create a Map<T, Boolean>. The second parameter type is whatever you want, I chose Boolean.
Create a new array named newArray; this will contain the unique values.
Iterate through the array. For each item perform the following:
Using the current arrayValue as the key, get the storedValue from the map.
if the storedValue is null (i.e. the Map.get() returned null) then this is a unique item. Insert the arrayValue, Boolean.TRUE into the map and add the arrayValue to the newArray.
if the storedValue is not null, then increment the duplicate count.
After iterating through the list, the newArray contains all non-duplicates and the duplicate count contains the count of duplicates.
1.
/**
* This method removes all duplicates from an array named "array"
* using a temporary List. So it converts the array into
* something like a Java set
*
* #return int number of duplicates removed
*/
public static int removeAll() {
int duplicates = 0;
List<Object> list = new ArrayList<>();
for(int i=0;i<array.length;i++){
Object element = array[i];
if(list.contains(element)) {
duplicates++;
}
else {
list.add(element);
}
}
array = list.toArray();
return duplicates;
}
2.
/**
* This method removes duplicates from an array named "array" using a
* temporary List.
* #param elementToBeRemoved
* #return int number of duplicates removed
*/
public static int removeAll(Object elementToBeRemoved) {
int duplicates = 0;
List<Object> list = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
Object element = array[i];
if (list.contains(elementToBeRemoved)) {
duplicates++;
} else {
list.add(element);
}
}
array = list.toArray();
return duplicates;
}
As this seems homework, no explanation, but this puzzle:
int lengthWithValues = array.length;
for (int i = 0; i < lengthWithValues; i++) {
// Loop invariant: for all at < i array is sorted, unique and complete.
int valueToBeChecked = array[i];
for (int k = i + 1, int j = i + 1; k < lengthWithValues; j++) {
if (array[j] == valueToBeChecked) {
--lengthWithValues; // Remove duplicate
} else {
array[k] = array[j]; // Maintain differing from all at <= i.
++k;
}
}
}
duplicatesRemoved = array.length - lengthWithValues;
// array[0 .. length - duplicatesRemoved] is the unique array.
int[] uniqueArray = new int[lengthWithValues];
System.arrayCopy(array, 0, uniqueArray, 0, lengthWithValues);
I'm coding in java and I need to create a function that returns the number of data objects that are currently in an ArrayList. At the moment I have this:
int count = 0;
for (int i = 0; i < data.length; i++)
{
if (data[i] != null)
{
count ++;
}
}
return count;
But the problem is that an array list that includes null data is acceptable, and I have to count their null data towards this counter. How do I include the null data that's in the middle of this array, and not the null data that's not supposed to be counted for?
For example, I have some tester code that adds (8),null,null,(23),(25) to the array, and this function should return 5 when the initial array size is 10.
I'm going to assume you're using a regular array (your question is somewhat ambiguous about this). Traverse through the array backwards until you find a non-null element:
public static int count(Object[] a) {
int i = a.length - 1;
for (; i >= 0 ; i--)
if (a[i] != null)
break;
return i + 1;
}
You could also have
public static <T> int count(T[] a) {
int i = a.length - 1;
for (; i >= 0 ; i--)
if (a[i] != null)
break;
return i + 1;
}
Let's test it out, using an example analogous to the one you provided:
Object[] a = new Object[10];
a[0] = new Object();
a[3] = new Object();
a[4] = new Object();
System.out.println(count(a));
Output:
5
You will need two separate counters. The first one will count normally. The second one starts counting when you find null data. Then when you find a non-null data, just add the second counter to the first one and continue counting with the first counter until you find a null again.
int count = 0;
for (int i = data.length - 1; i >= 0; i--)
if (data[i] != null || count > 0)
count += 1;
return count;
At least that's how I understood your requirements - count nulls, except for trailing nulls.
But maybe that's not actually what you meant?
Edit
Unless you're actually using ArrayList (as Jon was asking), where .size() is different from capacity and will count all added elements (including nulls). You can't actually even get the capacity from an ArrayList.