Nifty way to iterate over parallel arrays in Java using foreach

后端 未结 8 876
没有蜡笔的小新
没有蜡笔的小新 2020-12-13 04:29

I\'ve inherited a bunch of code that makes extensive use of parallel arrays to store key/value pairs. It actually made sense to do it this way, but it\'s sort of awkward to

相关标签:
8条回答
  • 2020-12-13 05:29

    This was a fun exercise. I created an object called ParallelList that takes a variable number of typed lists, and can iterate over the values at each index (returned as a list of values):

    public class ParallelList<T> implements Iterable<List<T>> {
    
        private final List<List<T>> lists;
    
        public ParallelList(List<T>... lists) {
            this.lists = new ArrayList<List<T>>(lists.length);
            this.lists.addAll(Arrays.asList(lists));
        }
    
        public Iterator<List<T>> iterator() {
            return new Iterator<List<T>>() {
                private int loc = 0;
    
                public boolean hasNext() {
                    boolean hasNext = false;
                    for (List<T> list : lists) {
                        hasNext |= (loc < list.size());
                    }
                    return hasNext;
                }
    
                public List<T> next() {
                    List<T> vals = new ArrayList<T>(lists.size());
                    for (int i=0; i<lists.size(); i++) {
                        vals.add(loc < lists.get(i).size() ? lists.get(i).get(loc) : null);
                    }
                    loc++;
                    return vals;
                }
    
                public void remove() {
                    for (List<T> list : lists) {
                        if (loc < list.size()) {
                            list.remove(loc);
                        }
                    }
                }
            };
        }
    }
    

    Example usage:

    List<Integer> list1 = Arrays.asList(new Integer[] {1, 2, 3, 4, 5});
    List<Integer> list2 = Arrays.asList(new Integer[] {6, 7, 8});
    ParallelList<Integer> list = new ParallelList<Integer>(list1, list2);
    for (List<Integer> ints : list) {
        System.out.println(String.format("%s, %s", ints.get(0), ints.get(1)));
    }
    

    Which would print out:

    1, 6
    2, 7
    3, 8
    4, null
    5, null
    

    This object supports lists of variable lengths, but clearly it could be modified to be more strict.

    Unfortunately I couldn't get rid of one compiler warning on the ParallelList constructor: A generic array of List<Integer> is created for varargs parameters, so if anyone knows how to get rid of that, let me know :)

    0 讨论(0)
  • 2020-12-13 05:33

    From the official Oracle page on the enhanced for loop:

    Finally, it is not usable for loops that must iterate over multiple collections in parallel. These shortcomings were known by the designers, who made a conscious decision to go with a clean, simple construct that would cover the great majority of cases.

    Basically, you're best off using the normal for loop.

    If you're using these pairs of arrays to simulate a Map, you could always write a class that implements the Map interface with the two arrays; this could let you abstract away much of the looping.

    Without looking at your code, I cannot tell you whether this option is the best way forward, but it is something you could consider.

    0 讨论(0)
提交回复
热议问题