简体   繁体   中英

iterating through multidimensional ArrayList

I am confused regarding iterating through a multidimensional ArrayList . I saw some topics about it and they seem complicated. in specific the accepted answer here: How to iterate through two dimensional ArrayList using iterator? can it be as in this method? which iterates through the arrayList and copy the value to an array:

private void reassembleArray(int[] array, ArrayList<ArrayList<Integer>> buckets) {
    Iterator<ArrayList<Integer>> it = buckets.iterator();   
    int i = 0;
    while (it.hasNext()) {
        ArrayList<Integer> intList = it.next();
        Iterator<Integer> itInteger = intList.iterator();
        while (itInteger.hasNext()) {
            array[i] = itInteger.next();
            i++;
       }
   }
}

are there any dangers or side effects for using this simple form?

this is the complete program which is an implementation of a sort algorithm called radix sort.

import java.util.ArrayList;
import java.util.Iterator;

/**
 * Radix sort implementation
 */
public class RadixSort {

/**
 * Runs the program
 */
public static void main(String[] args) {
  int[] array = {315, 418, 591, 260, 533, 58, 976, 938,};
  System.out.println("Radix sort implementation");
  printArray(array);
  sort(array, 3); // 3 is the maximun number of digits in all array elements to sort
  printArray(array);
}

/*
 * sort array of integers using radix sort algorithm
 * @param array The array
 * @param n the maximum number of digits in array elements
 */
private void sort(int[] array, int n) {
  int digitNumber = 0;
  while (digitNumber < n) {
    ArrayList<ArrayList<Integer>> buckets = initBuckets();
    // store each element in the bucket corresponding to the (digitNumber + 1)th 
    // digit of that element
    for (int i = 0; i < array.length; i++) {
      int value = array[i];
      int bucket = (value / (int) (Math.pow(10, digitNumber))) % 10;
      buckets.get(bucket).add(value);
    }
    reassembleArray(array, buckets);
    digitNumber++;
  }
}

/*
 * Initialize buckets ArrayList 
 * @return The buckets ArrayList
 */
private ArrayList<ArrayList<Integer>> initBuckets() {
  ArrayList<ArrayList<Integer>> buckets =  new ArrayList<ArrayList<Integer>>();
  // a bucket for each digit from 0 to 9
  for(int i = 0; i < 10; i++) {
    buckets.add(new ArrayList<Integer>());
  }
  return buckets;
}

/*
 * Reassemble the array 
 * @param array The array
 * @param buckets The buckets
 */
private void reassembleArray(int[] array, 
    ArrayList<ArrayList<Integer>> buckets) {
  Iterator<ArrayList<Integer>> it = buckets.iterator();   
  int i = 0;
  while (it.hasNext()) {
      ArrayList<Integer> intList = it.next();
      Iterator<Integer> itInteger = intList.iterator();
      while (itInteger.hasNext()) {
          array[i] = itInteger.next();
          i++;
      }
  }
}

/*
 * Prints an array of integers on a single line
 * @param array The array
 */
private void printArray(int[] array) {
  System.out.print("array: {");
  for (int i = 0; i < array.length; i++) {
    System.out.print(array[i] + ((i == array.length - 1) ?"" : ", "));
  }
  System.out.println("}");
}
}

The algorithm simply requires sorting the collection through a number of steps, first sort the collection according to the first digit to the right and have all the elements that in buckest of 0 - 9 according to that last digit while maintaining the initial order of the collection, then starting from bucket 0 reassemle the collection again and proceed to sorting according to the next digit to the left and so on.

the program does work and sorts the collection fine.

I bet the output you get is not the same one as you expect since the following line results in:

array[i] = itInteger.next();

Type mismatch: cannot convert from Integer to int[]

As far as I understand you want to convert List<List<Integer>> structure to the array of the same type. You also need to map Integer to int using Stream::mapToInt :

int array[][] = new int[buckets.size()][];
IntStream.range(0, buckets.size())
         .forEach(i -> array[i] = buckets.get(i)
                                         .stream()
                                         .mapToInt(j -> j.intValue())
                                         .toArray());

System.out.println(Arrays.deepToString(array));   // Prints the very same output

Also, you don't need to use Iterator , however if you insist on it:

int outerIndex = 0;
while (outerIterator.hasNext()) {
    List<Integer> list = outerIterator.next();
    Iterator<Integer> innerIterator = list.iterator();
    array[outerIndex] = new int[list.size()];
    int innerIndex = 0;
    while (innerIterator.hasNext()) {
        array[outerIndex][innerIndex] = innerIterator.next().intValue();
        innerIndex++;
    }
    outerIndex++;
}

Are there any dangers or side effects for using this simple form?

Yes, both of the solutions are since they don't amend the original resource of input nor affect another resource.

Your code will be clearer if you use enhanced for loops instead of iterators:

int i = 0;
for (List<Integer> intList : buckets) {
    for (int value : intList) {
        arr[i++] = value;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM