Split a List into chunks by an Element
Thank you guys Solution 1: hmm, I would like to solve your problem using a simple loop like this : Note, the question is not clear enough your Object class is named and the List of Object is which one is correct, In my answer I based to instead of . take a look at the Ideone demo Solution 2: with StreamEx library you can use method to split list for list of lists. Question: I have a collection of Objects (Pos) with this model : The list of objects is like this : I want to split this List of Objects by the the field of beforeChangement or afterChangement == «.»
Split a List into chunks by an Element
I have a collection of Objects (Pos) with this model :
The list of objects is like this :
[ Pos(beforeChangement=Découvrez, type=VER, afterChangement=découvrir), Pos(beforeChangement=un, type=DET, afterChangement=un), Pos(beforeChangement=large, type=ADJ, afterChangement=large), Pos(beforeChangement=., type=SENT, afterChangement=.), Pos(beforeChangement=Livraison, type=NOM, afterChangement=livraison), Pos(beforeChangement=et, type=KON, afterChangement=et), Pos(beforeChangement=retour, type=NOM, afterChangement=retour), Pos(beforeChangement=., type=SENT, afterChangement=.), Pos(beforeChangement=achetez, type=VER, afterChangement=acheter), Pos(beforeChangement=gratuitement, type=ADV, afterChangement=gratuitement), Pos(beforeChangement=., type=SENT, afterChangement=.), Pos(beforeChangement=allez, type=VER, afterChangement=aller), Pos(beforeChangement=faites, type=VER, afterChangement=faire), Pos(beforeChangement=vite, type=ADV, afterChangement=vite), Pos(beforeChangement=chers, type=ADJ, afterChangement=cher), Pos(beforeChangement=clients, type=NOM, afterChangement=client)] Pos(beforeChangement=., type=SENT, afterChangement=.) ]
I want to split this List of Objects by the the field of beforeChangement or afterChangement == «.» to have this format (A List of List) List> :
[ [Pos(beforeChangement=Découvrez, type=VER, afterChangement=découvrir), Pos(beforeChangement=un, type=DET, afterChangement=un), Pos(beforeChangement=large, type=ADJ, afterChangement=large)], [Pos(beforeChangement=Livraison, type=NOM, afterChangement=livraison), Pos(beforeChangement=et, type=KON, afterChangement=et), Pos(beforeChangement=retour, type=NOM, afterChangement=retour)], [Pos(beforeChangement=achetez, type=VER, afterChangement=acheter), Pos(beforeChangement=gratuitement, type=ADV, afterChangement=gratuitement)], [Pos(beforeChangement=allez, type=VER, afterChangement=aller), Pos(beforeChangement=faites, type=VER, afterChangement=faire), Pos(beforeChangement=vite, type=ADV, afterChangement=vite), Pos(beforeChangement=chers, type=ADJ, afterChangement=cher), Pos(beforeChangement=clients, type=NOM, afterChangement=client)] ]
Is like performing an inverse flatMap to have a List of Array or List (Chunks) after splitting by a field of object that is the String «.»
do you have any idea about how to do it using Streams ?
hmm, I would like to solve your problem using a simple loop like this :
List> result = new ArrayList<>(); List part = new ArrayList<>(); for(Pos pos : listPos)< if(pos.getBeforeChangement().equals(".") || pos.getAfterChangement().equals("."))< result.add(part);//If the condition is correct then add the sub list to result list part = new ArrayList<>();// and reinitialize the sub-list > else < part.add(pos);// else just put the Pos object to the sub-list >> //Just in case the listPos not end with "." values then the last part should not be escaped if(!part.isEmpty())
Note, the question is not clear enough your Object class is named SOP and the List of Object is Pos which one is correct, In my answer I based to public class Pos instead of public class SOP .
with StreamEx library you can use groupRuns method to split list for list of lists.
List> collect = StreamEx.of(originalList.stream()) .groupRuns((p1, p2) -> !(".".equals(p2.beforeChangement) || ".".equals(p2.afterChangement))) .collect(Collectors.toList());
Method groupRuns returns Stream of lists. In example above it are lists where first element with . .
You can filter out these elements later. For example using map method:
StreamEx.of(originalList.stream()) .groupRuns((p1, p2) -> !(".".equals(p2.beforeChangement) || ".".equals(p2.afterChangement))) // returns Stream of lists with '.' element .map(l -> l.stream() .filter(p -> !(".".equals(p.beforeChangement) || ".".equals(p.afterChangement))) //filter out element with '.' .collect(Collectors.toList())) .filter(l -> !l.isEmpty()) // filter out empty lists .collect(Collectors.toList());
Well, I would be conservative here, and I wouldn’t use Stream s (although it’s possible).
The following snippet does what you need:
List posList; List result = new ArrayList<>(); boolean startNewSentence = true; for (Pos pos : posList) < if (startNewSentence) < result.add(new ArrayList<>()); > startNewSentence = isPeriod(pos); if (!startNewSentence) < result.get(result.size() - 1).add(pos); >>
PS. Note there’s no such word as «changement» in English. The noun from verb «change» is also «change».
Collectors.groupingBy() may help you.
Java: how can I split an ArrayList in multiple small, You can use the chunk method from Eclipse Collections: ArrayList
Java 8 split a list into chunk for processing and merge it back before returning result [duplicate]
I am starting to play with streams in java 8 and I want to do something that feels should be possible but somehow cant seem to get it down.
I have to make call from my service to external service that can process at most 500 unique id and given time. My service can receive any number of this at a given time.
I am looking for a short and precise way to split the list of incoming id’s to size of 500 , make call to external service and merge them before returning me the result (Bonus if we can do this in parallel)
private List makeServiceCallByBatch(List ids,AuthToken authToken) < //make external call and get reply >public List makeServiceCall(List ids,AuthToken authToken) < private int BATCH_SIZE = 500; if(ids.size() >BATCH_SIZE) < //split by batch and process each batch and merge it all >else < return makeServiceCallByBatch(ids,authToken) >>
List has a sublist(int fromIndex, int toIndex) method that allows you to get a List of just the objects within a specific range in your bigger List . You can use this to pull out List s from your full List in intervals of 500 . So something like-
int index = 0; int batchSize = 500; while (index < ids.size()) < //used made up method name for doing whatever processing you need to do. processBatch(ids.sublist(index, Math.min(index + batchSize, ids.size())), authToken); index += batchSize; >
new ArrayList inputArrayList; //Write your array to inputArrayList here while (!inputArrayList.isEmpty()) < ArrayList newArrayList = new ArrayList(); for (int i = 0; i < 500 ; i++)< newArrayList.add(inputArray.lastIndexOf()); inputArray.remove(inputArray.lastIndexOf()); >// at this point in the while loop, your array of 500 items (newArrayList) should be full. be sure to process it // or move it to another array now, or it will be overwritten in the next iteration of the while loop. >
This code is meant only to show the process. It was written quickly, so it will need tweaking to fit into your app.
I’d go with a Stream API based solution:
List allReplies = IntStream.iterate(0, // start from 0 i -> i < ids.size(), // process until the last element i ->i + BATCH_SIZE) // iterate by BATCH_SIZE // extract the sublist from the initial one .mapToObj(i -> ids.subList(i, Math.min(i + BATCH_SIZE, ids.size())) // make the actual service call .map(ids -> makeServiceCallByBatch(ids, authToken)) // flatten the results into a single stream .flatMap(List::stream) // collect all the replies into one single list .collect(toList());
Java — Split a List into chunks by an Element, Split a List into chunks by an Element. Ask Question Asked 3 years, 10 months ago. Modified 3 years, 10 months ago. Viewed 604 times Java 8 List
Is there a common Java utility to break a list into batches?
I wrote myself a utility to break a list into batches of given size. I just wanted to know if there is already any apache commons util for this.
public static List getBatches(List collection,int batchSize)< int i = 0; List batches = new ArrayList(); while(i return batches; >
Please let me know if there any existing utility already for the same.
Check out Lists.partition(java.util.List, int) from Google Guava:
Returns consecutive sublists of a list, each of the same size (the final list may be smaller). For example, partitioning a list containing [a, b, c, d, e] with a partition size of 3 yields [[a, b, c] , [d, e]] — an outer list containing two inner lists of three and two elements, all in the original order.
In case you want to produce a Java-8 stream of batches, you can try the following code:
public static Stream batches(List source, int length) < if (length source.subList(n * length, n == fullChunks ? size : (n + 1) * length)); > public static void main(String[] args) < Listlist = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); System.out.println("By 3:"); batches(list, 3).forEach(System.out::println); System.out.println("By 4:"); batches(list, 4).forEach(System.out::println); >
By 3: [1, 2, 3] [4, 5, 6] [7, 8, 9] [10, 11, 12] [13, 14] By 4: [1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] [13, 14]
Use Apache Commons ListUtils.partition.
org.apache.commons.collections4.ListUtils.partition(final List list, final int size)
Another approach is to use Collectors.groupingBy of indices and then map the grouped indices to the actual elements:
final List numbers = range(1, 12) .boxed() .collect(toList()); System.out.println(numbers); final List groups = range(0, numbers.size()) .boxed() .collect(groupingBy(index -> index / 4)) .values() .stream() .map(indices -> indices .stream() .map(numbers::get) .collect(toList())) .collect(toList()); System.out.println(groups);
Java 8 split a list into chunk for processing and, List has a sublist(int fromIndex, int toIndex) method that allows you to get a List of just the objects within a specific range in your bigger List.You can use this to pull out Lists from your full List in intervals of 500.So something like-int index = 0; int batchSize = 500; while (index < ids.size()) < //used made up method …
Divide a list to lists of n size in Java 8
Every Java developer works with lists daily. There are many popular list (or collection) operations implemented in the standard Java 8 library, but there is one that is useful and commonly used, yet missing — partitioning. In this blog post, I would like to show you how you can split any list into chunks of fixed size without using any 3rd party library. Let’s start!
Introduction
Partitioning (also known as chunking) is an operation that transforms a collection of elements into a collection of chunks of a given size. For instance, let’s say we have a list of 7 elements (incrementing numbers from 1 to 7) and we want to split it into a list of chunks of size 2.
Let’s implement this operation using a new type of list, called Partition . We will extend the AbstractList> class, and we will implement two methods — get(int index) and size() . The whole idea here is to hide the original list inside this class and modify its behavior, so instead of returning single elements from the original list, we are going to return chunks of a given size. Let’s take a look at the code and the following example to make this concept much easier to understand.
package com.github.wololock; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public final class Partition extends AbstractList { private final List list; private final int chunkSize; public Partition(List list, int chunkSize) { this.list = new ArrayList<>(list); this.chunkSize = chunkSize; } public static Partition ofSize(List list, int chunkSize) { return new Partition<>(list, chunkSize); } @Override public List get(int index) { int start = index * chunkSize; int end = Math.min(start + chunkSize, list.size()); if (start > end) { throw new IndexOutOfBoundsException("Index " + index + " is out of the list range "); } return new ArrayList<>(list.subList(start, end)); } @Override public int size() { return (int) Math.ceil((double) list.size() / (double) chunkSize); } }
All we have to do is to override those two methods, and our list of elements starts behaving like a list of chunks of the input elements. Those overridden methods affect methods like toString() , forEach() , or iterator() . Let’s take a look at a simple usage example to see how this Partition object behaves:
final List numbers = Arrays.asList(1,2,3,4,5,6,7); System.out.println(Partition.ofSize(numbers, 3)); System.out.println(Partition.ofSize(numbers, 2));
Running this example will produce the following input to the console:
[[1, 2, 3], [4, 5, 6], [7]] [[1, 2], [3, 4], [5, 6], [7]]