how Can I fill an array bidimensional without a specific number of columns?
private Animals[] animals;
private Animals[][] matrizAnimal;
private final int MAX_ANIMALS = 20;
private int numAnimals;
CatalogueAnimals()
{
animals = new Animals[MAX_ANIMALS];
numAnimals = 4;
matrizAnimal = new Animals [2][];
animals[0] = new Dog("Pipi", 10);
animals[1] = new Cat("mimi", 4);
animals[2] = new Cat("jerry", 5);
animals[3] = new Cat("josh", 9);
}
public void fillArrayBi()
{
int i=0;
do{
for (int col=0; col<matrizAnimal.length; col++)
{
if (animals[i] instanceof Dog)
{
matrizAnimal[0][col] = animals[i];
}
else if (animals[i] instanceof Cat)
{
matrizAnimal[1][col] = animals[i];
}
i++;
}
}while(i<numAnimals);
}
I'm trying to fill the array. The first row contains 'Dogs' and the second row contains 'Cats'.
Thanks
for (int col=0; col<matrizAnimal.length; col++)
{
if (animals[i] instanceof Dog)
{
matrizAnimal[0][col] = animals[i];
}
...
}
This won't work due to a number of reasons:
col is bounded by the first dimension of matrizAnimal which is 2, thus it is somewhat risky to apply the value to the second dimension
you created matrizAnimal but I can't see any code where you initialize the elements, hence matrizAnimal[0][col] will result in a NullPointerException because the element at index 0 doesn't exist yet
If I understand your question correctly you want to create the 2nd dimension of matrizAnimal with a length calculated at runtime.
For that you'd have two options:
If you know the length when creating the second dimension, you can pass that directly to the construction call:
int lengthOfRow = 4;
matrizAnimal[0] = new Animals[lengthOfRow];
If the length depends on the elements in that second dimension array you could use a list, fill that and finally convert it to an array:
List<Animals> list = ...;
//fill list
matrizAnimal[0] = list.toArray(new Animals[list.size()]);
Edit:
To clarify on multi-dimensional arrays: arrays can only be one-dimensional but can contain other arrays. Hence a "multi-dimensional" array is actually an array containing arrays etc. In contrast to other languages like C++ the entire array is not laid out in contiguous memory.
In Java arrays need size to be declared, so you must know the number of columns when creating the array. I would make this approach in a different way using Collections
You can use 2 ArrayList, or if you want only one object, a Map:
Create and initialize Map
Map<String, List<Animals>> animalsMap = new HashMap<String, List<Animals>>();
Then,
if (animals[i] instanceof Dog)
{
if (animalsMap.get("Dog") != null)
{
animalsMap.put("Dog", animalsMap.get("Dog").add(animals[i]));
} else {
List<Animal> a = new ArrayList<Animal>();
a.add(animals[i]);
animalsMap.put("Dog", a);
}
}
else if (animals[i] instanceof Cat)
{
if (animalsMap.get("Dog") != null)
{
animalsMap.put("Cat", animalsMap.get("Dog").add(animals[i]));
} else {
List<Animal> a = new ArrayList<Animal>();
a.add(animals[i]);
animalsMap.put("Cat", a);
}
Related
I am new to Android and Java and can't figure out this seemingly basic for loop setup to create an array of objects from the data in two other arrays.
It works this way, but this doesn't feel very sophisticated.
// RefineMenuItem is a public class
public class RefineMenuItem {
private int imageIcon;
private String title;
}
// imageIcon and title are arrays with seven values in them
int[] imageItems = { ... }
String[] menuItems = { ... }
// Create the RefineMenu Objects
RefineMenuItem item1 = new RefineMenuItem(imageItems[0],menuItems[0]);
RefineMenuItem item2 = new RefineMenuItem(imageItems[1],menuItems[1]);
RefineMenuItem item3 = new RefineMenuItem(imageItems[2],menuItems[2]);
RefineMenuItem item4 = new RefineMenuItem(imageItems[3],menuItems[3]);
RefineMenuItem item5 = new RefineMenuItem(imageItems[4],menuItems[4]);
RefineMenuItem item6 = new RefineMenuItem(imageItems[5],menuItems[5]);
RefineMenuItem item7 = new RefineMenuItem(imageItems[6],menuItems[6]);
// Add the RefineMenu Objects to an ArrayList
ArrayList<RefineMenuItem> refineMenuList = new ArrayList<>();
refineMenuList.add(item1);
refineMenuList.add(item2);
refineMenuList.add(item3);
refineMenuList.add(item4);
refineMenuList.add(item5);
refineMenuList.add(item6);
refineMenuList.add(item7);
I believe I need to create the array of objects first and then add to it based on this question.
RefineMenuItem[] arr = new RefineMenuItem[7];
Then I believe I should use a for loop to add to the array, but this is where I'm getting stuck and can't figure it out after researching. Help to point me in the right direction is appreciated!
A basic for loop could solve all your problems I believe.
Just make sure you make your implementations/declarations before.
for(int i = 0; i<=6; i++) {
RefineMenuItem item = new RefineMenuItem(imageItems[i],menuItems[i]);
refineMenuList.add(item);
}
I'm gonna be brutally honest, haven't worked with java in a while so there might be some syntax errors but the logical solution should be supplemental.
It is impossible to create an ArraysList directly from two arrays. You first, need to create an array of the RefineMenuItem objects and add them. However, instead of creating a new array just to add all at once, create them as soon as you instantiate them... Like:
int size;
if(imageItems != null && menuItems != null && menuItems.length == imageItems.length) {
size = menuItems.length;
} else {
size = 0;
}
ArrayList<RefineMenuItem> refineMenuList = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
refineMenuList.add(new RefineMenuItem(imageItems[i],menuItems[i]));
}
A precondition is that imageItems and menuItems have the same number of elements in them. So I'd start by asserting that.
Then you can create a new array of the same size, and use a for loop to iterate:
int[] imageItems = { ... }
String[] menuItems = { ... }
if (imageItems.length != menuItems.length) {
throw new IllegalStateException("array lengths don't match");
}
RefineMenuItem[] result = new RefineMenuItem[imageItems.length];
for (int i = 0; i < imageItems.length; ++i) {
result[i] = new RefineMenuItem(imageItems[i], menuItems[i]);
}
When this code completes, the result array will be fully populated.
// RefineMenuItem is a public class
public class RefineMenuItem {
private int imageIcon;
private String title;
}
// imageIcon and title are arrays with seven values in them
int[] imageItems = { ... }
String[] menuItems = { ... }
// create array list
ArrayList<RefineMenuItem> refineMenuList = new ArrayList<>();
// add items to the array list in a for loop
for (int i = 0; i < imageItems.length; i++) {
refineMenuList.add(new RefineMenuItem(imageItems[i], menuItems[i]));
}
This is assuming the imageItems and menuItems are always the same length
The premise of this is you can create the ArrayList and then use a for loop to iterate over your imageItems and menuItems, create a new RefineMenuItem from them, and add it to the refineMenuList
you should be adding it to a class array this way:
import java.util.ArrayList.add
RefineMenuItem[] items = new RefineMenuItem();
for(int i=0 ; i<7 ; i++ ){
RefineMenuItem thing = new RefineMenuItem(RefineMenuItem(imageItems[i],menuItems[i])
items[i].add(i,thing))
}
I have a CarLot class, a Car class, and a CarLotApp class to set up a GUI for it. The CarLot is an ArrayList of Car objects. I have methods in CarLot that selection sort the CarLot based off of instance variables in Car (make, model, mpg,etc.)
For example:
public ArrayList<Car> getSortedDescMPG() {
ArrayList<Car> lotSortedByMPG = new ArrayList<Car>(myCars);
Car car;
for (Car c : lotSortedByMPG) {
double currentMax = c.getMPG();
car = c;
int currentMaxIndex = lotSortedByMPG.indexOf(c);
for (Car c2 : lotSortedByMPG) {
if (currentMax < c2.getMPG()) {
currentMax = c2.getMPG();
car = c2;
currentMaxIndex = lotSortedByMPG.indexOf(c2);
}
}
if (currentMaxIndex != lotSortedByMPG.indexOf(c)) {
lotSortedByMPG.set(currentMaxIndex, c);
lotSortedByMPG.set(lotSortedByMPG.indexOf(c), car);
}
}
return lotSortedByMPG;
}
I'm trying to get the sorted list into a TextArea in CarLotApp. In CarLotApp I also have three buttons, one to add a car, one to sort asc and one to sort desc, and a combo box to choose what instance variable to sort by.
class SortDesc extends WidgetViewerActionEvent {
#Override
public void actionPerformed(ActionEvent event) {
txtrSortedCarLot.setText("");
if (cmbSortOptions.getSelectedIndex() == 0)
txtrSortedCarLot.setText(myCarLot.toString());
else if (cmbSortOptions.getSelectedIndex() == 1)
txtrSortedCarLot.setText(CarLot.toString(myCarLot.getSortedDescMPG()));
else if (cmbSortOptions.getSelectedIndex() == 2)
etc...
}
}
The main issue is that the ArrayLists that were spat out from my sorting methods were out of order. I looked for similar posts but they all linked to one that focused on using a comparator to sort. I want to do this without useing compartors. So then I didn't really know what to search for since for what I can tell my sorting methods should work. So I don't know what I'm doing wrong.
When you do selection sort, the beginning of the array or list is becoming sorted, and you shouldn't look there for a maximum value. You rather want to find the maximum value in the remainder of the list, which is still unsorted. Your code was instead repeatedly finding the same car with maximum MPG.
Here's a working selection sort:
public static ArrayList<Car> getSortedDescMPG() {
ArrayList<Car> lotSortedByMPG = new ArrayList<>(myCars);
for (int i = 0; i < lotSortedByMPG.size(); i++) {
// At the beginning of each iteration, cars 0 through (i-1) are sorted
// Find the max-MPG car with index in the range (i, size-1) inclusive
Car carI = lotSortedByMPG.get(i);
int maxIndex = i;
Car maxCar = carI;
int maxMPG = carI.getMPG();
for (int j = i + 1; j < lotSortedByMPG.size(); j++) {
Car curCar = lotSortedByMPG.get(j);
int curMPG = curCar.getMPG();
if (curMPG > maxMPG) {
maxIndex = j;
maxCar = curCar;
maxMPG = curMPG;
}
}
// Now swap the max-MPG car (at index maxIndex) with car i (at index i)
lotSortedByMPG.set(i, maxCar);
lotSortedByMPG.set(maxIndex, carI);
}
return lotSortedByMPG;
}
This question already has answers here:
How to most elegantly iterate through parallel collections?
(8 answers)
Closed 6 years ago.
I Have Two Array Lists, Declared as:
ArrayList<JRadioButton> category = new ArrayList<JRadioButton>();
ArrayList<Integer> cat_ids = new ArrayList<Integer>();
Both of the these fields contain exactly, the Same No of Values, which are infact corresponding in Nature.
I know I can iterate over one of the loops like this:
for(JRadioButton button: category)
{
if(button.isSelected())
{
buttonName = button.getName();
System.out.println(buttonName);
}
}
But, I would like to iterate over both the LISTS simultaneously. I know they have the exact same size. How do I Do that?
You can use Collection#iterator:
Iterator<JRadioButton> it1 = category.iterator();
Iterator<Integer> it2 = cats_ids.iterator();
while (it1.hasNext() && it2.hasNext()) {
...
}
java8 style:
private static <T1, T2> void iterateSimultaneously(Iterable<T1> c1, Iterable<T2> c2, BiConsumer<T1, T2> consumer) {
Iterator<T1> i1 = c1.iterator();
Iterator<T2> i2 = c2.iterator();
while (i1.hasNext() && i2.hasNext()) {
consumer.accept(i1.next(), i2.next());
}
}
//
iterateSimultaneously(category, cay_id, (JRadioButton b, Integer i) -> {
// do stuff...
});
If you do this often you may consider using a helper function to zip two lists into one pair list:
public static <A, B> List<Pair<A, B>> zip(List<A> listA, List<B> listB) {
if (listA.size() != listB.size()) {
throw new IllegalArgumentException("Lists must have same size");
}
List<Pair<A, B>> pairList = new LinkedList<>();
for (int index = 0; index < listA.size(); index++) {
pairList.add(Pair.of(listA.get(index), listB.get(index)));
}
return pairList;
}
You will also need a Pair implementation. Apache commons lang package has a proper one.
And with these you can now elegantly iterate on the pairlist:
ArrayList<JRadioButton> category = new ArrayList<JRadioButton>();
ArrayList<Integer> cat_ids = new ArrayList<Integer>();
for (Pair<JRadioButton, Integer> item : zip(category , cat_ids)) {
// do something with JRadioButton
item.getLeft()...
// do something with Integer
item.getRight()...
}
Try this
ArrayList<JRadioButton> category = new ArrayList<JRadioButton>();
ArrayList<Integer> cat_ids = new ArrayList<Integer>();
for (int i = 0; i < category.size(); i++) {
JRadioButton cat = category.get(i);
Integer id= cat_ids.get(i);
..
}
ArrayList<JRadioButton> category = new ArrayList<JRadioButton>();
ArrayList<Integer> cat_ids = new ArrayList<Integer>();
Iterator<JRadioButton> itrJRB = category.iterator();
Iterator<Integer> itrInteger = cat_ids.iterator();
while(itrJRB.hasNext() && itrInteger.hasNext()) {
// put your logic here
}
Although you are expecting both sizes to be same, just to be on safer side get the sizes for both of them and make sure they are equal.
Let that size value be count. Then use generic for loop, iterate till count and acess the values as array indexes. If 'i' is the index, then acess as below in the for loop.
category[i] and cat_ids[i]
category[i].isSelected() and so on
For creating a UnboundedGrid and show it:
ActorWorld world = new ActorWorld(new UnboundedGrid<Actor>());
world.show();
For creating a BoundedGrid (let's say 10x10) and show it:
ActorWorld world = new ActorWorld(new BoundedGrid<Actor>(10, 10));
world.show();
There is any way to create a Custom UnboundedGrid?
By custom, I mean one of the parameters (cols or rows) is not unbounded.
I've checked UnboundedGrid's GridWorld source code and it extends AbstactGrid which implements Grid but I don't imagine any way of doing this.
The best idea is to implement it yourself by extending AbstractGrid. I suggest using an array of Maps that map integers representing the columns with the actors and the length of the array represents the number of rows. (Remember, you can't have generic arrays, so you have to use raw types.) Like this:
public class CustomUnboundedGrid<E> extends AbstractGrid<E>
{
private Map[] data;
private int cols;
public CustomUnboundedGrid(int rows, int cols)
{
if(cols <= 0)
throw new IllegalArgumentException();
try
{
data = new Map[rows];
for(int i = 0; i < rows; ++i)
{
data[i] = new HashMap();
}
}
catch(NegativeArraySizeException e)
{
throw new IllegalArgumentException();
}
}
//override methods from AbstractGrid
}
I want a function / data structure that can do this:
func(int dim){
if(dim == 1)
int[] array;
else if (dim == 2)
int[][] array;
else if (dim == 3)
int[][][] array;
..
..
.
}
anyone know how?
Edit
Or you could use Array.newInstance(int.class, sizes). Where sizes is an int[] containing the desired sizes. It will work better because you could actually cast the result to an int[][][]...
Original Answer
You could use the fact that both int[] and Object[] are Objects. Given that you want a rectangular multidimensional array with sizes given by the list sizes
Object createIntArray(List<Integer> sizes) {
if(sizes.size() == 1) {
return new int[sizes.get(0)];
} else {
Object[] objArray = new Object[sizes.get(0)];
for(int i = 0; i < objArray.length; i++) {
objArray[i] = createIntArray(sizes.subList(1, sizes.size());
}
return objArray;
}
}
You lose all static type checking, but that will happen whenever you want a dynamically dimensioned array.
If your purpose is to create a truly dynamic array, then you should look at the Array object in the JDK. You can use that to dynamically generate an array of any dimension. Here is an example:
public void func(int dim) {
Object array = Array.newInstance(int.class, new int[dim]);
// do something with the array
}
Once the array Object has been created, you can use the methods of the java.lang.reflect.Array class to access, add, remove elements from the multi-dimension array that was created. In also includes utility methods to determine the length of the array instance.
You can even check the dimension of the array using:
public int getDimension(Object array) {
int dimension = 0;
Class cls = array.getClass();
while (cls.isArray()) {
dimension++;
cls = cls.getComponentType();
}
return dimension;
}
People have post good solutions already, but I thought it'd be cool (and good practice) if you wrap the dynamic multidimensional array into a class, which can use any data structure to represent the multi-dimensional array. I use hash table so you have virtually unlimited size dimensions.
public class MultiDimArray{
private int myDim;
private HashMap myArray;
public MultiDimArray(int dim){
//do param error checking
myDim = dim;
myArray= new HashMap();
}
public Object get(Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
Object obj = myArray;
for (int i = 0; i < myDim; i++){
if(obj == null)
return null;
HashMap asMap = (HashMap)obj;
obj = asMap.get(indexes[i]);
}
return obj;
}
public void set(Object value, Integer... indexes){
if (indexes.length != myDim){throw new InvalidArgumentException();}
HashMap cur = myArray;
for (int i = 0; i < myDim - 1; i++){
HashMap temp = (HashMap)cur.get(indexes[i]);
if (temp == null){
HashMap newDim = new HashMap();
cur.put(indexes[i], newDim);
cur = newDim;
}else{
cur = temp;
}
}
cur.put(indexes[myDim -1], value);
}
}
and you can use the class like this:
Object myObj = new Object();
MultiDimArray array = new MultiDimArray(3);
array.put(myObj, 0, 1, 2);
array.get(0, 1, 2); //returns myObj
array.get(4, 5, 6); //returns null
What about a class like following?
class DynaArray {
private List<List> repository = new ArrayList<List>();
public DynaArray (int dim) {
for (int i = 0; i < dim; i++) {
repository.add(new ArrayList());
}
}
public List get(int i) {
return repository.get(i);
}
public void resize(int i) {
// resizing array code
}
}