2D Arrays and Generics Issue (Java) - java

I'm having an issue understanding some compiler-errors, regarding 2D arrays (ArrayList containing an ArrayList) and generics. My understanding of generics isn't the best, so I tried to research the issue beforehand and still ended up confused.
According to comments on 2D dynamic array using ArrayList in Java, you can't mix arrays with generics (or rather, you can with #SuppressWarnings("unchecked"), but are discouraged from doing so). However, I'm not sure what this exactly means.
Here is my problem code:
blocks = new ArrayList<ArrayList<BarrierBlock>>(columns); // initialize rows
for (int i = 0; i < columns; i++){
// blocks.get(i) = new ArrayList<BarrierBlock>(rows); <- ERROR = (unexpected type; required: variable, found: value)
blocks.add(new ArrayList<BarrierBlock>(rows)); // initialize columns
}
// initilize each block
for (int i = 0; i < blocks.size(); i++){
for (int j = 0; i < blocks.get(i).size(); j++){
int[] blockLoc = {location[0] + (i*BLOCK_SIDE_LENGTH), location[1] + (j*BLOCK_SIDE_LENGTH)};
// blocks.get(i).get(j) = new BarrierBlock(BLOCK_SIDE_LENGTH, blockLoc); <- ERROR = (unexpected type; required: variable, found: value)
blocks.get(i).add( new BarrierBlock(BLOCK_SIDE_LENGTH, blockLoc)); // initialize 2D array elements
}
}
The two lines that I commented out were my initial attempts at initializing the arrays. The compiler complained when I tried this and gave me the error listed. What does this error mean? I would think that both sides are of the declaration statement are variables.
After looking around, I found out that I'm supposed to use the add(E e) method of ArrayList. But what is the main difference? In the new way I'm initializing arrays, doesn't that also "mix arrays with generics"?

Get RETURNS the object at the given index, it can't be used to SET the object.
here are things you CAN do with get:
list l = new list();
item a;
l.add(a);
item b = l.get(0);
b.property = 10;
l.get(0).property == 10; //true, a is the same object as b
b = new item();
l.get(0) == b; //false, list[0] is still a, b is now pointing to a different object
l.get(0) = b; //error, you can't assign to list.get

Related

How can i delte an item from a 2D Array? [duplicate]

Given an array of n Objects, let's say it is an array of strings, and it has the following values:
foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";
What do I have to do to delete/remove all the strings/objects equal to "a" in the array?
[If you want some ready-to-use code, please scroll to my "Edit3" (after the cut). The rest is here for posterity.]
To flesh out Dustman's idea:
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
Edit: I'm now using Arrays.asList instead of Collections.singleton: singleton is limited to one entry, whereas the asList approach allows you to add other strings to filter out later: Arrays.asList("a", "b", "c").
Edit2: The above approach retains the same array (so the array is still the same length); the element after the last is set to null. If you want a new array sized exactly as required, use this instead:
array = list.toArray(new String[0]);
Edit3: If you use this code on a frequent basis in the same class, you may wish to consider adding this to your class:
private static final String[] EMPTY_STRING_ARRAY = new String[0];
Then the function becomes:
List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);
This will then stop littering your heap with useless empty string arrays that would otherwise be newed each time your function is called.
cynicalman's suggestion (see comments) will also help with the heap littering, and for fairness I should mention it:
array = list.toArray(new String[list.size()]);
I prefer my approach, because it may be easier to get the explicit size wrong (e.g., calling size() on the wrong list).
An alternative in Java 8:
String[] filteredArray = Arrays.stream(array)
.filter(e -> !e.equals(foo)).toArray(String[]::new);
Make a List out of the array with Arrays.asList(), and call remove() on all the appropriate elements. Then call toArray() on the 'List' to make back into an array again.
Not terribly performant, but if you encapsulate it properly, you can always do something quicker later on.
You can always do:
int i, j;
for (i = j = 0; j < foo.length; ++j)
if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);
You can use external library:
org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)
It is in project Apache Commons Lang http://commons.apache.org/lang/
See code below
ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);
If you need to remove multiple elements from array without converting it to List nor creating additional array, you may do it in O(n) not dependent on count of items to remove.
Here, a is initial array, int... r are distinct ordered indices (positions) of elements to remove:
public int removeItems(Object[] a, int... r) {
int shift = 0;
for (int i = 0; i < a.length; i++) {
if (shift < r.length && i == r[shift]) // i-th item needs to be removed
shift++; // increment `shift`
else
a[i - shift] = a[i]; // move i-th item `shift` positions left
}
for (int i = a.length - shift; i < a.length; i++)
a[i] = null; // replace remaining items by nulls
return a.length - shift; // return new "length"
}
Small testing:
String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4); // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a)); // [1, 2, null, null, null]
In your task, you can first scan array to collect positions of "a", then call removeItems().
There are a lot of answers here--the problem as I see it is that you didn't say WHY you are using an array instead of a collection, so let me suggest a couple reasons and which solutions would apply (Most of the solutions have already been answered in other questions here, so I won't go into too much detail):
reason: You didn't know the collection package existed or didn't trust it
solution: Use a collection.
If you plan on adding/deleting from the middle, use a LinkedList. If you are really worried about size or often index right into the middle of the collection use an ArrayList. Both of these should have delete operations.
reason: You are concerned about size or want control over memory allocation
solution: Use an ArrayList with a specific initial size.
An ArrayList is simply an array that can expand itself, but it doesn't always need to do so. It will be very smart about adding/removing items, but again if you are inserting/removing a LOT from the middle, use a LinkedList.
reason: You have an array coming in and an array going out--so you want to operate on an array
solution: Convert it to an ArrayList, delete the item and convert it back
reason: You think you can write better code if you do it yourself
solution: you can't, use an Array or Linked list.
reason: this is a class assignment and you are not allowed or you do not have access to the collection apis for some reason
assumption: You need the new array to be the correct "size"
solution:
Scan the array for matching items and count them. Create a new array of the correct size (original size - number of matches). use System.arraycopy repeatedly to copy each group of items you wish to retain into your new Array. If this is a class assignment and you can't use System.arraycopy, just copy them one at a time by hand in a loop but don't ever do this in production code because it's much slower. (These solutions are both detailed in other answers)
reason: you need to run bare metal
assumption: you MUST not allocate space unnecessarily or take too long
assumption: You are tracking the size used in the array (length) separately because otherwise you'd have to reallocate your array for deletes/inserts.
An example of why you might want to do this: a single array of primitives (Let's say int values) is taking a significant chunk of your ram--like 50%! An ArrayList would force these into a list of pointers to Integer objects which would use a few times that amount of memory.
solution: Iterate over your array and whenever you find an element to remove (let's call it element n), use System.arraycopy to copy the tail of the array over the "deleted" element (Source and Destination are same array)--it is smart enough to do the copy in the correct direction so the memory doesn't overwrite itself:
System.arraycopy(ary, n+1, ary, n, length-n)
length--;
You'll probably want to be smarter than this if you are deleting more than one element at a time. You would only move the area between one "match" and the next rather than the entire tail and as always, avoid moving any chunk twice.
In this last case, you absolutely must do the work yourself, and using System.arraycopy is really the only way to do it since it's going to choose the best possibly way to move memory for your computer architecture--it should be many times faster than any code you could reasonably write yourself.
Something about the make a list of it then remove then back to an array strikes me as wrong. Haven't tested, but I think the following will perform better. Yes I'm probably unduly pre-optimizing.
boolean [] deleteItem = new boolean[arr.length];
int size=0;
for(int i=0;i<arr.length;i==){
if(arr[i].equals("a")){
deleteItem[i]=true;
}
else{
deleteItem[i]=false;
size++;
}
}
String[] newArr=new String[size];
int index=0;
for(int i=0;i<arr.length;i++){
if(!deleteItem[i]){
newArr[index++]=arr[i];
}
}
I realise this is a very old post, but some of the answers here helped me out, so here's my tuppence' ha'penny's worth!
I struggled getting this to work for quite a while before before twigging that the array that I'm writing back into needed to be resized, unless the changes made to the ArrayList leave the list size unchanged.
If the ArrayList that you're modifying ends up with greater or fewer elements than it started with, the line List.toArray() will cause an exception, so you need something like List.toArray(new String[] {}) or List.toArray(new String[0]) in order to create an array with the new (correct) size.
Sounds obvious now that I know it. Not so obvious to an Android/Java newbie who's getting to grips with new and unfamiliar code constructs and not obvious from some of the earlier posts here, so just wanted to make this point really clear for anybody else scratching their heads for hours like I was!
Initial array
int[] array = {5,6,51,4,3,2};
if you want remove 51 that is index 2, use following
for(int i = 2; i < array.length -1; i++){
array[i] = array[i + 1];
}
EDIT:
The point with the nulls in the array has been cleared. Sorry for my comments.
Original:
Ehm... the line
array = list.toArray(array);
replaces all gaps in the array where the removed element has been with null. This might be dangerous, because the elements are removed, but the length of the array remains the same!
If you want to avoid this, use a new Array as parameter for toArray(). If you don`t want to use removeAll, a Set would be an alternative:
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
Set<String> asSet = new HashSet<String>(Arrays.asList(array));
asSet.remove("a");
array = asSet.toArray(new String[] {});
System.out.println(Arrays.toString(array));
Gives:
[a, bc, dc, a, ef]
[dc, ef, bc]
Where as the current accepted answer from Chris Yester Young outputs:
[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]
with the code
String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };
System.out.println(Arrays.toString(array));
List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);
System.out.println(Arrays.toString(array));
without any null values left behind.
My little contribution to this problem.
public class DeleteElementFromArray {
public static String foo[] = {"a","cc","a","dd"};
public static String search = "a";
public static void main(String[] args) {
long stop = 0;
long time = 0;
long start = 0;
System.out.println("Searched value in Array is: "+search);
System.out.println("foo length before is: "+foo.length);
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
System.out.println("==============================================================");
start = System.nanoTime();
foo = removeElementfromArray(search, foo);
stop = System.nanoTime();
time = stop - start;
System.out.println("Equal search took in nano seconds = "+time);
System.out.println("==========================================================");
for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
}
public static String[] removeElementfromArray( String toSearchfor, String arr[] ){
int i = 0;
int t = 0;
String tmp1[] = new String[arr.length];
for(;i<arr.length;i++){
if(arr[i] == toSearchfor){
i++;
}
tmp1[t] = arr[i];
t++;
}
String tmp2[] = new String[arr.length-t];
System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length);
arr = tmp2; tmp1 = null; tmp2 = null;
return arr;
}
}
It depends on what you mean by "remove"? An array is a fixed size construct - you can't change the number of elements in it. So you can either a) create a new, shorter, array without the elements you don't want or b) assign the entries you don't want to something that indicates their 'empty' status; usually null if you are not working with primitives.
In the first case create a List from the array, remove the elements, and create a new array from the list. If performance is important iterate over the array assigning any elements that shouldn't be removed to a list, and then create a new array from the list. In the second case simply go through and assign null to the array entries.
Arrgh, I can't get the code to show up correctly. Sorry, I got it working. Sorry again, I don't think I read the question properly.
String foo[] = {"a","cc","a","dd"},
remove = "a";
boolean gaps[] = new boolean[foo.length];
int newlength = 0;
for (int c = 0; c<foo.length; c++)
{
if (foo[c].equals(remove))
{
gaps[c] = true;
newlength++;
}
else
gaps[c] = false;
System.out.println(foo[c]);
}
String newString[] = new String[newlength];
System.out.println("");
for (int c1=0, c2=0; c1<foo.length; c1++)
{
if (!gaps[c1])
{
newString[c2] = foo[c1];
System.out.println(newString[c2]);
c2++;
}
}
Will copy all elements except the one with index i:
if(i == 0){
System.arraycopy(edges, 1, copyEdge, 0, edges.length -1 );
}else{
System.arraycopy(edges, 0, copyEdge, 0, i );
System.arraycopy(edges, i+1, copyEdge, i, edges.length - (i+1) );
}
If it doesn't matter the order of the elements. you can swap between the elements foo[x] and foo[0], then call foo.drop(1).
foo.drop(n) removes (n) first elements from the array.
I guess this is the simplest and resource efficient way to do.
PS: indexOf can be implemented in many ways, this is my version.
Integer indexOf(String[] arr, String value){
for(Integer i = 0 ; i < arr.length; i++ )
if(arr[i] == value)
return i; // return the index of the element
return -1 // otherwise -1
}
while (true) {
Integer i;
i = indexOf(foo,"a")
if (i == -1) break;
foo[i] = foo[0]; // preserve foo[0]
foo.drop(1);
}
to remove  only the first  of several equal entries
with a lambda
boolean[] done = {false};
String[] arr = Arrays.stream( foo ).filter( e ->
! (! done[0] && Objects.equals( e, item ) && (done[0] = true) ))
.toArray(String[]::new);
can remove null entries
In an array of Strings like
String name = 'a b c d e a f b d e' // could be like String name = 'aa bb c d e aa f bb d e'
I build the following class
class clearname{
def parts
def tv
public def str = ''
String name
clearname(String name){
this.name = name
this.parts = this.name.split(" ")
this.tv = this.parts.size()
}
public String cleared(){
int i
int k
int j=0
for(i=0;i<tv;i++){
for(k=0;k<tv;k++){
if(this.parts[k] == this.parts[i] && k!=i){
this.parts[k] = '';
j++
}
}
}
def str = ''
for(i=0;i<tv;i++){
if(this.parts[i]!='')
this.str += this.parts[i].trim()+' '
}
return this.str
}}
return new clearname(name).cleared()
getting this result
a b c d e f
hope this code help anyone
Regards
Assign null to the array locations.

Error while checking specific value at index is null

I have below list defined,
List<BigDecimal> empList = new ArrayList<BigDecimal>();
And as per below code if condition throws error The type of the expression must be an array type but it resolved to List
for(int i1=0;i1<12;i1++) {
if(empList[i1]==null){
empList[i1]= new BigDecimal("0.00");
}
}
The same code works well in Groovy but does not work in Java.
Looks like a syntax error . In java list are accessed as
empList.get(i1)
and
empList.set(i1,new BigDecimal("0.00"))
or you are free to use array instead of List but in this case you will have to define the array length which stays fixed.
BigDecimal[] empList = new BigDecimal[10];
It has to be :
for (int i1 = 0; i1 < 12; i1++) {
if (empList.get(i1) == null) {
empList.set(i1, new BigDecimal("0.00"));
}
}
A list collection needs has its own methods. Use those.

Java Creating Objects at Runtime in a For Loop

I'm trying to create objects within a for loop at runtime. Here is the (incorrect) code:
for(int i=1;i<max;i++){
Object object(i);
}
I'd like it to create max number of Object objects with names object1, object2, etc. Is there any way to do this? I have been unable to find anything elsewhere online. Thanks for your help!
You want to use a data structure to store a sequence of objects. For example, an array could do this:
Fruit banana[] = new Fruit[10];
for (int i = 0; i < 10; i++){
banana[i] = new Fruit();
}
This creates 10 objects of type Fruit in the banana array, I can access them by calling banana[0] through banana[9]
You could use an array to create multiple objects.
public void method(int max) {
Object[] object = new Object[max];
for (int i = 0; i < max; i++) {
object[i] = new Object();
}
}

Using a list in java

So I had a question, which I won't go into too much detail because I managed to correctly code it into an array. Or at least, code it into an array that worked correctly; as follows:
static double getSolution (int n)
{
double [] w = new double [n];
w[0] = -1;
for (int i = 0; i < n; i++)
{
w[i + 1] = w[i] + (( 2 / 3*n ) * Math.cos (w[i]) );
}
double x = w[n];
return x;
}
I then found out I was not meant to have coded it using an array, but instead using a list. I have attempted this, and the following is the code I have come up with:
static double getSolution1 (int n)
{
List <double> w = new ArrayList <double>();
w[0] = -1;
for (int i = 0; i < n; i++)
{
w[i+1] = w[i] + ((2 / 3*n ) * Math.cos (w[i]) );
}
return w[n];
}
Now I know this is wrong from the start off, but could anybody tell me what I have done wrong and where? Also; when attempted to compile I get the error message "cannot find symbol - class List".
EDIT 1: I have tried changing the line to Double instead of double has many people have suggested, I am still getting the exact same compiling error.
EDIT 2: So if I was to transcribe the array into a list, what would the correct code be? Because I'm really confused as to how I'm supposed to write it out.
Use
List <Double> w = new ArrayList <Double>();
instead of
List <double> w = new ArrayList <double>();
double is a primitive type but list will accept only object so thats use Double. Double is a wrapper over primitive type double.
Edit:
w[0] this is not list operation so if you are using this type of operation to access element you should use array. else mperform add remove operations
Check List operations: http://docs.oracle.com/javase/6/docs/api/java/util/List.html
you must declare import statement for packages
import java.util.List;
import java.util.ArrayList;
so Your method become
Using array
static double getSolution1 (int n)
{
Double[] w = new Double[n+1];
w[0] = -1d;
for (int i = 0; i < n; i++)
{
w[i+1] = w[i] + ((2 / 3*n ) * Math.cos (w[i]) );
}
return w[n];
}
Using List
static double getSolution1(int n) {
List<Double> w = new ArrayList<Double>();
w.add(-1d);
for (int i = 0; i < n; i++) {
double d = w.get(i) + ((2 / 3 * n) * Math.cos(w.get(i)));
w.add(d);
}
return w.get(n);
}
Generics are meant to be used for classes, not for primitive types.
Just change the code to use Double instead of double:
List <Double> w = new ArrayList <Double>();
You shoule have
List <Double> w = new ArrayList <Double>();
instead of
List <double> w = new ArrayList <double>();
Because collection framework does not allow primitive data type, it only accepts Wrapper classes of the primitive data type.
In java each primary data type has its Object type.
e.g.
int --> Integer
double --> Double
byte --> Byte
If you want to put your primary data into a collections, you need to declare the collection with the number's corresponding Object type.
So,
List <Double> w = new ArrayList <Double>();
will work.
And
double d = 12.34;
w.add(d);
will also work. Java will convert d into Double type automatically. The mechanism is called auto-boxing.
You should only use a List where the data is not always a fixed size. They add extra overhead compared to a regular array.
To create a List object, use an implementation like ArrayList.
ArrayList<Double> w = new ArrayList<Double>();
You also don't access a list via [].
w.get(index) // Gets value. Throws exception if index is greater than or equal to size() or less than 0.
w.add(index, value); // Adds value
w.set(index, value); // Replaces value
You get that error because you have not imported the List interface and the ArrayList class. Insert this code at the beginning of the file:
import java.util.List;
import java.util.ArrayList;
Alternatively, you can do this (no imports needed):
static double getSolution1 (int n)
{
//If you do the import, remove the java.util. that follows.
//This also fixes the other errors.
java.util.List <Double> w = new java.util.ArrayList<Double>();
//w[0] = -1; //this does not work; a list is not an array.
w.add(-1.0);
for (int i = 0; i < n; i++)
{
//w[i+1] = w[i] + ((2 / 3*n ) * Math.cos (w[i]) ); this does not work either;
// just add the result to the list.
w.add(w.get(i) + ((2 / 3*n ) * Math.cos (w.get(i) );
}
return w.get(n);
}
Here is an explanation of the changes I made (other than java.util.List or the imports):
For the generic type, double does not work. You need to use a Double (the wrapper class for a double), thus the code changes from List<double> to List<Double>. This is necessary to Java because of Type Erasure. At compile time, the generic type is removed and the List is treated as if it were a list of Objects. Since primitives are not Objects, we need the wrapper class.
Rather than using w[0]=-1;, we use w.add(-1);. w is an object, not an array, thus cannot be accessed with [number]. Luckily, List has some useful methods; namely List#add() and List#get(). Calling w.add(-1) appends -1 to the end of the list.
For the w[i+1] part in the loop, we simply add the new element, using w.get(i) rather than w[i].

HashSet compilation error

The only thing I want to do is putting an array (temp_X) into a HashSet, but I got the error for the HashSet: no suitable constructor found for HashSet(List)
public PSResidualReduction(int Xdisc[][], double[][] pat_cand, int k) {
for (int i = 0; i < Xdisc.length; i++) {
int[] temp_X;
temp_X = new int[Xdisc[0].length];
for (int s = 0; s < Xdisc[0].length; s++) {
temp_X[s] = Xdisc[i][s];
}
HashSet<Integer> temp_XList = new HashSet<Integer>(Arrays.asList(temp_X));
}
}
Any idea how I can fix it?
Arrays#asList accepts a type array which means all elements used need to be Object types rather than primitives.
Use an Integer array instead:
Integer[] temp_X;
This will allow Arrays#asList to be used to against the wrapper class:
HashSet<Integer> temp_XList = new HashSet<Integer>(Arrays.asList(temp_X));
in Arrays.asList(temp_X); temp_X must be a Object array,not primitive type array. And HashSet<T> does not support primitive type .You have to convert each int in temp_X to Integer and add to temp_xList one by one

Categories