taking elements from all arrayLists one at a time - java

considering there is a structure as described in http://prohost.lt/stack/q.png
In the main arrayList we have n elements(sub arrayLists) (as for image we can consider n=3).
How to make a dynamic loop thru all sub arrayLists so as to get:
sarraylist1.get(0), sarrayList2.get(0), .. sarraylistN.get(0)
In case n=3 it would be
for(sarraylist1){
for( sarraylist2){
for(sarraylist3){
element from every list
}
}
}

Maybe I misunderstood what you were asking, but would something as simple as this not work?
List<List> lists = new ArrayList<List>();
for(List l : lists){
for(List subl: l)
Object o = subl.get(0);
}

Based on your scheme of the image, you can also do it with the "for while loop":
for (int mainArrayElements = 0; mainArrayElements < listOfLists.size(); mainArrayElements++) {
List arraysInMain = ((List)listOfLists.get(mainArrayElements));
for (int subArrayElements = 0; subArrayElements < arraysInMain.size(); subArrayElements++) {
List deepArray = ((List)listOfLists.get(subArrayElements));
for (int innerArrayElements = 0; innerArrayElements < deepArray.size() ; innerArrayElements++) {
System.out.println(deepArray.get(innerArrayElements));
}
}
}
But as mentioned before, recursion would be a really great combo to knock out the problem :).
Best regards.

If I understood correctly, you have one List containing n Lists for which you want to get the first, second and so on, element of each list. This code does that.
for (int i = 0; i < highestSizeOfChildrenList; i++) {
List<Object> lstOfItemInChild = new Arraylist<Object>();
for (List childList : mainList) {
if (i < childList.size()) {
lstOfItemInChild.add(childList.get(i));
}
}
// lstOfItemInChild now contains all the element i of the sub arrays
}
You will need to know the size of the biggest subList to get all the elements of that list, that is what highestSizeOfChildrenList represents.

After watching your comment I suggest you to use recursive approach to solve your problem.
public void recursiveCall(ArrayList list)
{
for ( Object obj : list)
{
if (obj instanceOf ArrayList)
{
recursiveCall((ArrayList)obj);
}
else
{
System.out.print(obj);
}
}
}

Related

Using an Iterator inside a for loop to remove elements from an ArrayList

I have an ArrayList of objects that have a version number as a field. I want to do some work on that ArrayList, but I only want the most recent version of the object. I was thinking of coding as such:
ArrayList<ObjectVO> ObjectList = getObjectList();
for(ObjectVO myVO : ObjectList) {
Iterator<ObjectVO> iter = ObjectList.iterator();
while(iter.hasNext()) {
ObjectVO checkVO = iter.next();
if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
iter.remove();
}
}
}
}
Is this valid? I don't know if the fact that we are in a for loop originally would break the mutability of the ArrayList at runtime.
No, this won't work. iter.remove() will cause the out for loop to fail with ConcurrentModificationException.
Instead of doing this, you can do this with indexed for loops, and a BitSet to keep track of things you want to remove:
BitSet toRemove = new BitSet();
for (int m = 0; m < ObjectList.size(); ++m) {
if (toRemove.get(m)) continue;
ObjectVO myVO = ObjectList.get(m);
for (int c = 0; c < ObjectList.size(); ++c) {
if (toRemove.get(c)) continue;
ObjectVO checkVO = ObjectList.get(c);
if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
toRemove.set(c);
}
}
}
}
This is basically your code, but it doesn't do the removal yet. Then you can sweep through the list after and remove them:
int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (!toRemove.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();
The point of using a BitSet like this is that removal from an ArrayList is inefficient if you are removing from anywhere other than the end, because it requires all of the elements "to the right" of the element you remove to be shuffled along by one position. The loop with the set/get and clear allows you to only move each of the retained elements once.
You can do a bit better than the quadratic loop, though, if you group the list elements by things with the same ID: then you don't need to keep on checking the entire list:
BitSet toKeep = new BitSet();
IntStream.range(0, ObjectList.size())
.mapToObj(a -> a)
.collect(
groupingBy(a -> ObjectList.get(a).getID(),
maxBy(comparingInt(a -> ObjectList.get(a).getVersion()))))
.values()
.forEach(a -> toKeep.set(a));
int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (toKeep.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();
Assuming you have the memory, rather than do an O(N^2) operation, you could do this more efficiently (O(N)) by using a Map to track the newest Version for each Id. One pass tracks the newest version for each Id, and the second removes elements which are not the latest.
Map<Integer, Thing> newestById = new HashMap<>();
for (Thing thing : list) {
newestById.merge(thing.id, thing, (a,b) -> a.version > b.version ? a : b);
}
list.removeIf(thing -> thing != newestById.get(thing.id)); }
Depending on your use case, you might even be able to store your data in a Map instead of a List, and check if the version is the latest before adding it to the Map.
As the other answers have discussed this won't work. You have three options as I see them, trading memory for CPU cycles/flexibility. I've used Integer instead of ObjectVO in my examples, but it'll be trivial to swap them.
Option 1 - moderate memory, single-pass of the array
Track the highest ID you've seen and populate an ArrayList with new items as they meet the criteria. When you encounter a new higher ID, throw away the ArrayList and create a new one:
ArrayList<Integer> objectList = getObjectList();
Integer bestId = -1;
ArrayList<Integer> allObjectsMatchingId = new ArrayList<>();
for(Integer currentObject : objectList) {
if(currentObject > bestId) {
bestId = currentObject;
allObjectsMatchingId = new ArrayList<>();
} else if(currentObject == bestId) {
allObjectsMatchingId.add(currentObject);
}
}
return allObjectsMatchingId;
Option 2 - more expensive memory, single-pass of the array, most flexible.
For each ID you see, create an ArrayList and store it against a map. This allows you to easily change the criteria about what ID you want to keep.
ArrayList<Integer> objectList = getObjectList();
Map<Integer, ArrayList<Integer>> objectsById = new HashMap<>();
for(Integer currentObject : objectList) {
ArrayList<Integer> listForId = objectsById.get(currentObject);
if(listForId == null) {
listForId = new ArrayList<Integer>();
}
listForId.add(currentObject);
objectsById.put(currentObject, listForId);
}
Integer bestId = -1;
for(Integer i : objectsById.keySet()) {
if(i > bestId) {
bestId = i;
}
}
return objectsById.get(bestId);
Option 3 - no additional memory aside from id, two-passes of the array.
Search through the ArrayList for the highest ID, then filter the array to only elements that pass that filter.
This is the closest to your current implementation, the difference being that you do them in separate steps. This reduces complexity from O(N^2) to O(N), and is valid as you aren't modifying the ArrayList while iterating it. You could use a Stream here to filter instead of an iterator if you're Java 8 compatible. See Java: Efficient ArrayList filtering?
ArrayList<Integer> objectList = getObjectList();
Integer bestId = -1;
for(Integer currentObject : objectList) {
if(currentObject > bestId) {
bestId = currentObject;
}
}
Iterator<Integer> iter = objectList.iterator();
while(iter.hasNext()) {
if(iter.next() != bestId) {
iter.remove();
}
}
Why not use Java Streams to solve this:
Collection<ObjectVO> result = objectList.stream()
.collect(Collectors.toMap(ObjectVO::getID, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(ObjectVO::getVersion))))
.values();
This creates a map which contains the max version for each id. Then you can just use Map.values() to get the object list.
If you need a List or an ArrayList you can just use new ArrayList<>(result).

classify the values inside array list inside list in java

I am trying to develop a method which receives a List of ArrayList and classify the array list inside it based on the object value. Then, return array list that contains the objects have 1 in their FirstChoice.
the data structure in my code is that
the List has n number of ArrayList, the ArrayList has 24 objects. each object has 3 elements and FirstChoice is one of these elements.
The problem of my code is the output not as i expect , it seems to be just stick with one value and repeat it for the whole list. could you please help me to fix that
ArrayList<HH> TestMethods(List<ArrayList<HH>> s) {
ArrayList<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (int i = 0; i < d.size(); i++) {
if (s.get(i).get(i).FirstChoice == 1) {
scenario.add(s.get(i).get(i));
}
}
}
return scenario;
}
The problem in your code is that when you are looping over the list s, you are actually never using the current element d.
Some other comments on your code:
Prefer returning a List instead of an ArrayList.
Name your methods and variables according to Java naming conventions (testMethods instead of TestMethods, firstChoice instead of FirstChoice)
Be consistent in the way you write loops: use foreach or an index but keep to the same style.
List<HH> testMethods(List<ArrayList<HH>> s) {
List<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (HH hh : d) {
if (hh.firstChoice == 1) {
scenario.add(hh);
}
}
}
return scenario;
}
Your mistakes are on these lines if (s.get(i).get(i).FirstChoice == 1) { and scenario.add(s.get(i).get(i)); as you aren't actually user inner list d.
You're referencing the i'th element of the i'th list of s, when I think you want the i'th element of d where d is a list from s.
ArrayList<HH> TestMethods(List<ArrayList<HH>> s) {
ArrayList<HH> scenario = new ArrayList<HH>();
for (ArrayList<HH> d : s) {
for (int i = 0; i < d.size(); i++) {
int item = d.get(i).FirstChoice;
if (item == 1) {
scenario.add(item);
}
}
}
return scenario;
}

Sorting Objects in ArrayList giving unexpected results

Here record is an ArrayList of objects of the type Employee. I am trying to sort the ArrayList based on the employeeName attribute. Unfortunately, it gives unwanted results.
public void sortByName(){
for(int i = 0; i < SalesDataManager.N; i++){
for(int j = i+1; j < SalesDataManager.N; j++){
if(record.get(i).getEmployeeName().compareToIgnoreCase(record.get(j).getEmployeeName()) > 0){
Employee etemp = record.get(i);
record.add(i,record.get(j));
record.add(j,etemp);
}
}
}
displayAllRecords();
}
I have gone through other posts in stackoverflow regarding this topic and found out that most of the post suggest this same way.Am I doing something wrong here?
Thanks in advance!
You are iterating the record list and according to some condition determining where to add the current element. However, you aren't emptying the list first, so this approach will inevitably lead to duplications.
Java, luckily, has a built it mechanism for such sorting - you just need to implement a Comparator:
public class EmployeeNameComparator implements Comparator<Emplyoee> {
#Override
public int compare (Employee a, Employee b) {
return a.getEmployeeName().compareToIgnoreCase(b.getEmployeeName());
}
And then just use it:
Collections.sort (record, new EmployeeNameComparator());
If you're using Java 8, you could also use the new cleaner syntax:
Collections.sort
(record, (a, b) -> a.getEmployeeName().compareToIgnoreCase(b.getEmployeeName());
#Howard Wang and Mureinik, you guys were right. The add(index,object) method added the object to the index and was right-shifting the already existing object, instead of replacing it, which was what I was intending to achieve. So, adding record.remove(i+1); and record.remove(j+1); to the code did the trick!
public void sortBySales()
{
for(int i = 0; i < SalesDataManager.N; i++)
{
for(int j = i+1; j < SalesDataManager.N; j++)
{
if(record.get(i).getEmployeeSales() > record.get(j).getEmployeeSales())
{
Employee etemp = record.get(i);
record.add(i,record.get(j));
record.remove(i+1);
record.add(j,etemp);
record.remove(j+1);
}
}
}
}

Merge two lists on index

I have two lists containing the same type of objects. Each object has an int, a string and some other stuff where the int is its index.
Here is the object that both lists are holding:
public class ListElement
{
private int index;
private String data;
private String some;
private String other;
private String stuff;
// gets, sets...
}
What i want is to take List A's index and "some other stuff" and replace its string "data" with the one from List B. The one it takes from List B should match the index of List A. I hope this is understandable.
EDIT: It should be noted that the index int inside the object has nothing to do with the actual position of the object in the list. Its for other porpuses
UPDATE: You mentioned that the index field of your ListElement has no relationship with its actual place in its containing List.
You just happen to have a field with a random name that you want to compare both list on (join on). This solution uses nested loops to compare every element in one list with every element in the other list.
for (int iA = 0; iA < listA.size(); iA++) //iterate over listA
{
ListElement currentElement = listA.get(iA);
for (int iB = 0; iB < listB.size(); iB++) //iterate over listB
{
ListElement other = listB.get(iB);
if (other.index == currentElement.index) //compare the elements
{
//do stuff
currentElement.setData(other.getData());
break; //if only want first match
}
}
}
Assuming your both list have the same number of elements, you could do something like:
ListElement sourceElement, destElement;
for (int i =0; i<list1.size(); i++) {
sourceElement = list1.get(0);
destElement = list2.get(0);
sourceElement.setData(destElement.getData());
...
}
The first idea is probably not the brightest but I'll come to that later.
For (ListElement e : ListA) {
For (ListElement le : ListB) {
if (e.getIndex() = le.getIndex()) {
e.setData(le.getData());
}
}
}
So this is my first shot for what you wrote, but it's probably not the easiest way. To make it simpler and faster you could implement the interface Comparable and use sort, i this case you access the List elements by the index in ListElement (assuming you assure the indices are complete from 1..n).
My favored solution would be to use some kind of maps to store the index as key, and the ListElement as value, then it's just MapA.get(i).setData(MapB.get(i).getData()) This is fool-prove, as long as for every item in MapA there is an according item in MapB with the same index.
If you want to match on the index field on the ListItem object, try this:
for (ListItem listItemA : listA) {
for (ListItem listItemB : listB) {
if (listItemB.getIndex() == listItemA.getIndex()) {
listItemA.setData(listItemB.getData());
}
}
}
If you're interested in matching based on index within the List objects, try
for (int i = 0; i < listA.size(); i++) {
listA.get(i).setData(listB.get(i).getData());
}

dividing arraylist into multiple arraylists

My program creates an arraylist of 5000 to 60000 records depending on time of day. I want to split it into as many arraylists as possible that each arraylist will have 1000 records. I looked at many examples online and tried a few things but I ran into strange problems. Can you please show me an example of this?
Regards!
public static <T> Collection<Collection<T>> split(Collection<T> bigCollection, int maxBatchSize) {
Collection<Collection<T>> result = new ArrayList<Collection<T>>();
ArrayList<T> currentBatch = null;
for (T t : bigCollection) {
if (currentBatch == null) {
currentBatch = new ArrayList<T>();
} else if (currentBatch.size() >= maxBatchSize) {
result.add(currentBatch);
currentBatch = new ArrayList<T>();
}
currentBatch.add(t);
}
if (currentBatch != null) {
result.add(currentBatch);
}
return result;
}
Here's how we use it (assuming emails an a large ArrayList of email addresses:
Collection<Collection<String>> emailBatches = Helper.split(emails, 500);
for (Collection<String> emailBatch : emailBatches) {
sendEmails(emailBatch);
// do something else...
// and something else ...
}
}
where emailBatch would iterate over the collection like this:
private static void sendEmails(Collection<String> emailBatch){
for(String email: emailBatch){
// send email code here.
}
}
You can use the subList http://docs.oracle.com/javase/6/docs/api/java/util/List.html#subList from List to split your ArrayList. The sublist will give you a view of the original list. If you really want to create a new list, separate from the old one, you could do something like:
int index = 0;
int increment = 1000;
while ( index < bigList.size() ) {
newLists.add(new ArrayList<Record>(bigList.subList(index,index+increment));
index += increment;
}
Note you'll have to check for off by one errors here. This is just a quick pseudocode sample.

Categories

Resources