Iterating through an array List and creating new ArrayLists when values are different, is this even possible?

11,462

Solution 1

Yes you can do this but it's really annoying to write in Java. Note: This is a brain dead simple in a functional programming language like Clojure or Haskell. It's simply a function called group-by. In java, here's how I'd do this:

  1. Initialize a List of Lists.
  2. Create a last pointer that is a List. This holds the last list you've added to.
  3. Iterate the raw data and populate into the last as long as "nothing's changed". If something has changed, create a new last.

I'll show you how:

package com.sandbox;

import java.util.ArrayList;
import java.util.List;

public class Sandbox {

    public static void main(String[] args) {
        ArrayList<String> rawInput = new ArrayList<String>();
        rawInput.add("80");
        rawInput.add("80");
        rawInput.add("60");
        rawInput.add("60");
        new Sandbox().groupBy(rawInput);
    }

    public void groupBy(List<String> rawInput) {
        List<List<String>> output = new ArrayList<>();
        List<String> last = null;

        for (String field : rawInput) {
            if (last == null || !last.get(0).equals(field)) {
                last = new ArrayList<String>();
                last.add(field);
                output.add(last);
            } else {
                last.add(field);
            }
        }

        for (List<String> strings : output) {
            System.out.println(strings);
        }
    }
}

This outputs:

[80, 80]
[60, 60]

Of course, you can do what the other guys are suggesting but this changes your data type. They're suggesting "the right tool for the job", but they're not mentioning guava's Multimap. This will make your life way easier if you decide to change your data type to a map.

Here's an example of how to use it from this article:

public class MutliMapTest {
    public static void main(String... args) {
  Multimap<String, String> myMultimap = ArrayListMultimap.create();

  // Adding some key/value
  myMultimap.put("Fruits", "Bannana");
  myMultimap.put("Fruits", "Apple");
  myMultimap.put("Fruits", "Pear");
  myMultimap.put("Vegetables", "Carrot");

  // Getting the size
  int size = myMultimap.size();
  System.out.println(size);  // 4

  // Getting values
  Collection<string> fruits = myMultimap.get("Fruits");
  System.out.println(fruits); // [Bannana, Apple, Pear]

  Collection<string> vegetables = myMultimap.get("Vegetables");
  System.out.println(vegetables); // [Carrot]

  // Iterating over entire Mutlimap
  for(String value : myMultimap.values()) {
   System.out.println(value);
  }

  // Removing a single value
  myMultimap.remove("Fruits","Pear");
  System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]

  // Remove all values for a key
  myMultimap.removeAll("Fruits");
  System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
 }
}

Solution 2

It sounds to me like a better choice would be a Map of Lists. Let the company ID be the key in the Map and append each new item for that company ID to the List that's the value.

Use the right tool for the job. Arrays are too low level.

Solution 3

Create a Map<String, List<Bussiness>>

Each time you retrieve a company name, first check if the key is already in the map. If it is, retrieve the list and add the Bussiness object to it. If it is not, insert the new value when a empty List and insert the value being evaluated.

Share:
11,462
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I am fairly new to Java and I have stumbled across a problem I cannot figure out for the life of me. First let me explain what I am trying to do then I will show you the code I have so far.

    I have a webservice that returns an array of arrays(which include company and lines of business strings). I wish to transform this into a string list, which I did in the first line of code below. Then I wish to Iterate through the list and every I come across a different value for company, I want to create a new ArrayList and add the associated line of business to the new list. Example output of webservice: 80,80,64,64 (this is presorted so the same companies will always be grouped together) the associated lobs would be 1,2,3,4 respectively. What I want: arraylist[0]: 1,2 arrayList[1]: 3,4

    What I have so far:

        List coList = Arrays.asList(coArray);
        //create list of lists
        List<List<String>> listOfLists = new ArrayList<List<String>>();
        String cmp = "";
        for (int i=0;i<coList.size();i++){//loop over coList and find diff in companies
            String currentCo = ((__LOBList)coList.get(i)).getCompany();
            String currentLob = ((__LOBList)coList.get(i)).getLobNum();
            if(i<coArray.length-1){
                String nextCo = ((__LOBList)coList.get(i+1)).getCompany();
                if((currentCo.equals(nextCo))){
                    //do nothing companies are equal
                }else{
                    log("NOT EQUAL"); //insert logic to create a new array??
                    ArrayList<String> newList = new ArrayList<String>();
            //      for(int j=0;j<coList.size();j++){
                    newList.add( ((__LOBList)coList.get(i)).getLobNum());                   
            //      }   
    
    
                    for(int k=0; k<listOfLists.size();k++){//loop over all lists
                        for(int l=0;l<listOfLists.get(k).size();l++){ //get first list and loop through
    
                        }
                        listOfLists.add(newList);   
                    }
    
                }
            }
    
    
        }
    

    My problem here is that it is not adding the elements to the new string array. It does correctly loop through coList and I put a log where the companies are not equal so I do know where I need to create a new arrayList but I cannot get it to work for the life of me, please help!

  • Admin
    Admin almost 11 years
    Awesome, thanks for the help! I didn't even realize a multimap existed, Here is a question though. If I wanted to keep the data in the type __LOBList (which has several string fields) is there a way to do this with the multimap? I am just thinking down the line that I may need use some of the information that I would be discarding If I used the company as a key and the lines of businesses as values
  • Rana Ghosh
    Rana Ghosh almost 11 years
    @Eric Yes, the Multimap.put takes <K,V>. It can be any object you want.
  • Rana Ghosh
    Rana Ghosh almost 11 years
    @Eric I may have misunderstood. If __LOBList is the list of values (rather than the values), you'd have to implement your own Multimap interface to do that. It's probably easier than it sounds because I'm sure there's an abstract class you can just extend that does 90% of the work for you. Alternatively, you can just add a constructor on __LOBList that takes a list and knows how to convert it. That seems even easier.
  • Admin
    Admin almost 11 years
    thanks for the update, sorry if I wasn't clear I had such a long day yesterday and I may have left out key information. Basically __LOBList holds a list of values, and after my webservice runs it returns an array(results) of objects(__LOBList) which has strings that hold the values. I am trying to iterate through the list,(which is dynamic the number and values of the objects might change), and create a new array of __LOBList objects that all have a common value in the field 'company', and then from here I am going to create new htmlSelectManyCheckbox groups(JSF)
  • Admin
    Admin almost 11 years
    So basically whenever the value of 'company' is different it will create a new arrayList and store all the objects with the same company in that list