A better method to eliminate having to create many lists to pare down to the required items.

I am a beginner.
I am being passed a list of values into a method.
Out of the List of value I have to perform evaluarion on the items in the
list with these types 'CISCO', 'IP', 'SRV'.  The List will contain other types but these are the ones that require evaluation.  
If type CISCO has a defict in cost
and there is a surplus for type IP with the same serial as CISCO , set CISCO excess to IP surplus. if type IP has a deficit in cost and type SRV with the same serial as IP has surplus set IP excess to SRV surplus

The items in the list are:   name  type  serial cost  laborcost  excess

The only way that I know how to do this is to create 6 lists .  Is there a better way to do this?
 
What I'm current doing is
 looping through the passed list
  if type = 'CISCO' and cost < laborCost
      ADD TO deficitCISCOList
 if type = 'IP' and cost < laborCost
     ADD TO deficitIPList

Create the surplus list
   if type = 'IP' and cost > laborCost
      add to excessIPList
  if type = 'SRV' and cost > laborCost
      add to excessSRVList

loop through
    deficitCISCOList
      loop through excessIPList
         if IPCost serial = CISCO serial
            update  deficitCISCOList excess with  excessIPList laborCost
            add to adjustCISCOList

loop through
 deficitIPList
    loop through excessSRVList
         if IPCost serial = SRV serial
            update  deficitIPList excess with  excessSRVList
                                                   laborCost
            add to adjustIPList

After that, I loop through the adjustCISCOList and the list passed to the method  until I find the matching type and serial and update the passed list excess.
cookiejarAsked:
Who is Participating?
 
mccarlConnect With a Mentor IT Business Systems Analyst / Software DeveloperCommented:
I did ask that the sample was compilable, but anyway... I fixed it so that it does compile, but there may be a small chance that I changed your logic in the process. This shouldn't matter to this discussion though.

In the code below I have added a method that does the processing how I would do it. You will more than likely have to change the actual processing down in the flowDown method, but again that is not exactly what this question is about. (Note that this was hard because your code contradicts it self, and the description that you provided above, so I will leave that part up to you)

However, the main point about this code is how two find pairs of items in the list and then perform some processing. So here is a brief description of what it is doing... It finds the first item (and stores that in the map of previous items for later) It is a CISCO with serial 201, and it hasn't previously seen any IP item with serial 201, so it does nothing. The next item is an IP item with serial 201, now it looks in the map and finds a CISCO with serial 201, so it can now do its processing. It has a reference to both items, so it can retrieve whatever fields it needs and it can also set new values for whatever fields. When you look at the code, there are two "if" blocks for each CISCO<->IP and IP<->SRV. That is because those items could appear if either order, ie. CISCO then IP, or IP then CISCO, so it handles both cases.

Also, note that the above processing is based on the assumption that there will only ever be 1 item for a Type/Serial combination, ie. you CAN'T have "ItemA, CISCO, 201" and "ItemB, CISCO, 201". If that is the case, then my method won't work, but I doubt that is the case.

The important lines are between 44 and 93.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ItemProcessingExample {
    public static void main(String[] args) {
        List<Item> items = Arrays.asList(new Item[] { 
                new Item("ItemA", "CISCO", "201", 50, 100, 0), 
                new Item("ItemB", "IP", "201", 200, 20, 0), 
                new Item("ItemC", "SRV", "100", 800, 200, 0), 
                new Item("ItemD", "IP", "100", 400, 600, 0), 
                new Item("ItemE", "IP", "111", 100, 50, 0), 
                new Item("ItemG", "AVA", "111", 100, 50, 0),
        
        });
        System.out.println(items);
        processitemsList(items);
        System.out.println(items);
        
        System.out.println();
        
        
        
        // Test using mccarl's method
        List<Item> itemsCopy = Arrays.asList(new Item[] { 
                new Item("ItemA", "CISCO", "201", 50, 100, 0), 
                new Item("ItemB", "IP", "201", 200, 20, 0), 
                new Item("ItemC", "SRV", "100", 800, 200, 0), 
                new Item("ItemD", "IP", "100", 400, 600, 0), 
                new Item("ItemE", "IP", "111", 100, 50, 0), 
                new Item("ItemG", "AVA", "111", 100, 50, 0),
        
        });
        System.out.println(itemsCopy);
        processitemsList_MCCARLS_method(itemsCopy);
        System.out.println(itemsCopy);
    }
    
    
    // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
    
    private static void processitemsList_MCCARLS_method(List<Item> items) {
        Map<String, Item> previousItems = new HashMap<String, Item>();
        
        for (Item item : items) {
            previousItems.put(item.getType() + item.getSerial(), item);
            
            
            // Process CISCO - IP items
            if ("CISCO".equals(item.getType())) {
                Item ipItem = previousItems.get("IP" + item.getSerial());
                if (ipItem != null) {
                    // item (which is a CISCO) and ipItem (which is an IP) have the same serial number, so we can just do your required processing
                    flowDown(ipItem, item);
                }
            }
            if ("IP".equals(item.getType())) {
                Item ciscoItem = previousItems.get("CISCO" + item.getSerial());
                if (ciscoItem != null) {
                    // item (which is a IP) and ciscoItem (which is an CISCO) have the same serial number, so we can just do your required processing
                    flowDown(item, ciscoItem);
                }
            }
            
            
            // Process SRV - IP items
            if ("SRV".equals(item.getType())) {
                Item ipItem = previousItems.get("IP" + item.getSerial());
                if (ipItem != null) {
                    // item (which is a SRV) and ipItem (which is an IP) have the same serial number, so we can just do your required processing
                    flowDown(item, ipItem);
                }
            }
            if ("IP".equals(item.getType())) {
                Item srvItem = previousItems.get("SRV" + item.getSerial());
                if (srvItem != null) {
                    // item (which is a IP) and srvItem (which is an SRV) have the same serial number, so we can just do your required processing
                    flowDown(srvItem, item);
                }
            }
        }
    }

    private static void flowDown(Item flowDownFromItem, Item flowDownToItem) {
        if (flowDownToItem.getCost() < flowDownToItem.getLaborCost() && 
                flowDownFromItem.getCost() > flowDownFromItem.getLaborCost()) {
            double deficitVariance = flowDownToItem.getCost() - flowDownToItem.getLaborCost();
            flowDownToItem.setExcess(deficitVariance);
            flowDownFromItem.setCost(flowDownFromItem.getCost() - deficitVariance);
        }
    }
    
    
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    private static void processitemsList(List<Item> items) {
    // This is where we will implement your logic

        List<Item> ciscoList = new ArrayList<Item>();
        List<Item> ipList = new ArrayList<Item>();
        List<Item> srvList = new ArrayList<Item>();

        // Load ciscos, ips and srvs into 3 separate lists
        for (Item vo : items) // these are from fake array right now
        {

            if (0 == vo.getType().compareTo("IP"))
            {
                ipList.add(vo);
            }

            if (0 == vo.getType().compareTo("CISCO"))
            {
                ciscoList.add(vo);
            }

            if (0 == vo.getType().compareTo("SRV"))
            {
                srvList.add(vo);
            }

        }

        // Get ciscos and ips with deficits
        List<Item> deficitciscoList = new ArrayList<Item>();
        List<Item> deficitipList = new ArrayList<Item>();

        deficitciscoList = getciscosWithDeficit(ciscoList, deficitciscoList);
        deficitipList = getipsWithDeficit(ipList, deficitipList);

        // flow down from ips to ciscos; flow down form ips to srvs
        List<Item> flowdownipList = new ArrayList<Item>();
        List<Item> flowdownsrvList = new ArrayList<Item>();

        flowdownipList = flowdownsipTocisco(deficitciscoList, ipList,
                flowdownipList);
        flowdownsrvList = flowdownssrvToip(deficitipList, srvList,
                flowdownsrvList);

        
        /*  I would like to update Item with  flowdownipList and flowdownsrvList  lists.
       Expected Update List
         
	    Item ("ItemA", "CISCO", "201", 50, 100, 50),
            Item ("ItemB", "IP",    "201", 150, 20, 0),
            Item ("ItemC", "SRV",   "100", 600, 200, 0),
            Item ("ItemD", "IP",    "100", 400, 600, 200),
            Item ("ItemE", "IP",    "111", 100 50, 0),
            Item ("ItemG", "AVA",   "111", 100 50, 0),
        	   
       */

    }
    
    public static List<Item> getciscosWithDeficit(List<Item> ciscoList, List<Item> deficitciscoList) {
        for (Item vo : ciscoList) {
            if (vo.getCost() < vo.getLaborCost()) {
                deficitciscoList.add(vo);
            }
        }
        
        return deficitciscoList;
    }
    
    public static List<Item> getipsWithDeficit(List<Item> ipList, List<Item> deficitipList) {
        for (Item vo : ipList) {
            if (vo.getCost() < vo.getLaborCost()) {
                deficitipList.add(vo);
            }
        }
        
        return deficitipList;
    }
    
    public static List<Item> flowdownsipTocisco(List<Item> deficitciscoList, List<Item> ipList, List<Item> flowdownipList) {
        double deficitVariance = 0;
        int flowdownQty = 0;
        
        for (Item ciscovo : deficitciscoList) {
            for (Item ipvo : ipList) {
                if (ciscovo.getSerial()
                        .equals(ipvo.getSerial()) && ipvo.getCost() > ipvo.getLaborCost()) {
                    deficitVariance = ciscovo.getCost() - ciscovo.getLaborCost();
                    
                    // Set to the amount of excess needed
                    ciscovo.setExcess(deficitVariance);
                    
                    // Subtract the amount that is flowed down to cisco from ip
                    // Cost.
                    ipvo.setCost(ipvo.getCost() - deficitVariance);
                    
                    // Add the updated ciscos and ips to the list.
                    flowdownipList.add(ciscovo);
                    flowdownipList.add(ipvo);
                    break;
                }
            }
        }
        return flowdownipList;
    }
    
    public static List<Item> flowdownssrvToip(List<Item> deficitipList, List<Item> srvList, List<Item> flowdownsrvList) {
        double deficitVariance = 0;
        int flowdownQty = 0;
        
        for (Item ipvo : deficitipList) {
            for (Item srvvo : srvList) {
                if (ipvo.getSerial()
                        .equals(srvvo.getSerial()) && srvvo.getCost() > srvvo.getLaborCost()) {
                    deficitVariance = ipvo.getCost() - ipvo.getLaborCost();
                    
                    // Set to the amount of excess needed
                    ipvo.setExcess(deficitVariance);
                    
                    // Subtract the amount that is flowed down to ip from srv
                    // Cost.
                    srvvo.setCost(ipvo.getCost() - deficitVariance);
                    
                    // Add the updated ciscos and ips to the list.
                    flowdownsrvList.add(ipvo);
                    flowdownsrvList.add(srvvo);
                    break;
                }
            }
        }
        return flowdownsrvList;
    }
    
    private static class Item {
        public String name;
        public String type;
        public String serial;
        public double cost;
        public double laborCost;
        public double excess;
        
        public Item(String name, String type, String serial, double cost, double laborCost, double excess) {
            this.name = name;
            this.type = type;
            this.serial = serial;
            this.cost = cost;
            this.laborCost = laborCost;
            this.excess = excess;
        }

        public String getName() {
            return name;
        }

        public String getType() {
            return type;
        }

        public String getSerial() {
            return serial;
        }

        public double getCost() {
            return cost;
        }

        public void setCost(double cost) {
            this.cost = cost;
        }

        public double getLaborCost() {
            return laborCost;
        }

        public double getExcess() {
            return excess;
        }

        public void setExcess(double excess) {
            this.excess = excess;
        }

        @Override
        public String toString() {
            return "Item [name=" + name + ", type=" + type + ", serial=" + serial + ", cost=" + cost + ", laborCost=" + laborCost + ", excess=" + excess + "]";
        }
    }
}

Open in new window

0
 
gudii9Commented:
How are items in the list  are related?
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Can you write a compilable, self-contained example of this so that we have something to work with? Something along the lines of...
public class ItemProcessingExample {
  public static void main(String[] args) {
    List<Item> items = new ArrayList<Item>();
    items.add(new Item("My Name", "CISCO", "1234AB765S", 0.5, 0.8, 1.2));
    // continue the above to add all the example items

    processItemsList(items);

    System.out.println(items);
  }

  private static void processItemsList(List<Item> items) {
    // This is where we will implement your logic
  }

  private static class Item {
    public String name;
    public String type;
    // etc, etc for each field

    public Item(String name, String type /* etc, etc for each field to be initialised*/) {
      this.name = name;
      this.type = type;
      // etc, etc
    }
  }
}

Open in new window

Now if you flesh the above out, with extra example items that show the conditions that you expect and have the right values that will exercise your above logic, AND give us what the expected output should be, ie. list all items that should be there AFTER the method is run AND all the field values for each item. Then we have something to work with where we can provide code to go inside that method and show you some ways to avoid using so many lists.

Check out this site: http://sscce.org/ for a guide on good ways to pose coding problems.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
cookiejarAuthor Commented:
I have attached the sample code.

The question is how can I optimize the attached code.  I think I a looping through too many lists.
SAMPLE.txt
0
 
cookiejarAuthor Commented:
What does previousItems.get("IP" + item.getSerial()) do?
0
 
cookiejarAuthor Commented:
Does  previousItems.get("IP" + item.getSerial())  guarantee that this will get the same sertial as the CISCO.
0
 
cookiejarAuthor Commented:
If the first item is not always cisco will this work?
0
 
mccarlIT Business Systems Analyst / Software DeveloperCommented:
What does previousItems.get("IP" + item.getSerial()) do?
It finds the previously seen IP item with the same serial as the current item (CISCO or SRV depending on if you are talking about line 53 or line 70). It may or may not be there, depending on the order of the items, so that call will either return the object or return null. So yes, it guarantees that it will only bring back an item with the SAME serial.

If the first item is not always cisco will this work?
Yes, it will still work. That is what I was trying to highlight in the last part of my previous post. If the first item is an IP and then later there is a CISCO (with the same serial) then the "if" block at lines 52-58 will pick that up. But if the CISCO is first followed by the IP, as in your example, then the "if" block at lines 59-65 is what will find that.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.