There is an ArrayList:
public void mainMethod() {
List<String> list = new ArrayList<>();
list.add("'+7913152','2020-05-25 00:00:25'");
list.add("'8912345','2020-05-25 00:01:49'");
list.add("'916952','2020-05-25 00:01:55'");
}
and method which transforms a string:
public String doTransform(String phone) {
String correctNumber;
..... make some changes...
return correctNumber;
}
list.stream().forEach(line -> {
Arrays.stream(line.split(","))... and what else?
How to take only first element of sub-stream (Arrays.stream) and pass it to transforming method?
"doTransform()" method is implemented, so don't care about it.
I just need to separate '+7913152', '8912345' and '916952', pass it to doTransform() and get an new List:
"'8913152','2020-05-25 00:00:25'"
"'8912345','2020-05-25 00:01:49'"
"'8916952','2020-05-25 00:01:55'"
Do it as follows:
List<String> result = list.stream()
.map(s -> {
String[] parts = s.split(",");
String st = doTransform(String.valueOf(Integer.parseInt(parts[0].replace("'", ""))));
return ("'" + st + "'") + "," + parts[1];
}).collect(Collectors.toList());
Demo:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("'+7913152','2020-05-25 00:00:25'");
list.add("'8912345','2020-05-25 00:01:49'");
list.add("'916952','2020-05-25 00:01:55'");
List<String> result = list.stream()
.map(s -> {
String[] parts = s.split(",");
String st = doTransform(String.valueOf(Integer.parseInt(parts[0].replace("'", ""))));
return ("'" + st + "'") + "," + parts[1];
}).collect(Collectors.toList());
// Display
result.forEach(System.out::println);
}
static String doTransform(String phone) {
return "x" + phone;
}
}
Output:
'x7913152','2020-05-25 00:00:25'
'x8912345','2020-05-25 00:01:49'
'x916952','2020-05-25 00:01:55'
I am assuming that length of the phone no in string as e.g "'+7913152','2020-05-25 00:00:25'" will be 7 if it's more than that you are going the remove the rest numbers from the head and replace with 8 to make it valid number else if number length is less than 7 then you will simply append the 8, Note: you can handle if the length of the number is like 3 or 4 etc.
public class PlayWithStream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("'+7913152','2020-05-25 00:00:25'");
list.add("'8912345','2020-05-25 00:01:49'");
list.add("'916952','2020-05-25 00:01:55'");
List<String> collect = list.stream()
.map(PlayWithStream::doTransform)
.collect(Collectors.toList());
System.out.println(collect);
}
public static String doTransform(String phone1) {
String []a=phone1.split(",");
String phone=a[0];
boolean flag2 = phone.substring(0, 1).matches("[8]");
String finaloutput="";
if(!flag2) {
int len=phone.length();
if(len>7) {
String sub=phone.substring(0,phone.length()-6);
String newStr=phone.replace(sub, "");
finaloutput="8".concat(newStr);
}else {
finaloutput="8".concat(phone);
}
}
return finaloutput+","+a[1];
}
}
We can split elements using , in only two parts (initial which need to be change and remaining String) using limit on split String split.
List<String> list = list.stream()
.map(input -> input.split(",", 2))
.map(data -> String.join(",", doTransaform(data[0]), data[1]))
.collect(Collectors.toList());
It can be helpful when your string has multiple commas (,) separated parts and will surely improve efficiency too.
The below code works,
List<String> collect = list.stream()
.map(a -> a.replace(String.valueOf(a.charAt(1)), "2"))
.collect(Collectors.toList());
Related
I have two lists of Pearson (variables: FirstName, LastName, AllFirstName). One of them contains duplicates (if a pearson has two first names then in that list will have two entries for each name but the lastname will be the same) and one of them has only unique values (listWithUniquePearsons). The second list will be created by itereting over the first list and putting all the first name in a list of objects. I wrote this with two for. Is there any way to write it as a stream?
for (Pearson prs : listWithUniquePearsons) {
List<String> firstNames = new ArrayList<String>();
for (Pearson tempPerson : allPearsons) {
if (prs.getLastName().equals(tempPerson.getLastName())) {
firstNames.add(tempPerson.firstNames());
}
}
if (firstNames.size()>1) {
prs.setAllFirstNames(firstNames);
}
}
List<String> firstNames = listWithUniquePearsons
.stream()
.map(prs -> allPearsons.stream()
.filter(tempPerson -> prs.getLastName().equals(tempPerson.getLastName()))
.map(Person::getFirstName)
.collect(Collectors.toList());
You should build a map with a key lastName and values List<FirstName> and then remap its entries back to Pearson class setting allFirstNames. This can be done using Java 8 streams and collectors.
Let's assume that class Pearson is implemented as follows:
import java.util.*;
public class Pearson {
private String firstName;
private String lastName;
private List<String> allFirstNames;
public Pearson(String first, String last) {
this.firstName = first;
this.lastName = last;
}
public Pearson(List<String> allFirst, String last) {
this.allFirstNames = allFirst;
this.lastName = last;
}
public String getFirstName() {return firstName; }
public String getLastName() {return lastName; }
public List<String> getAllFirstNames() {return allFirstNames; }
}
Test code:
import java.util.*;
import java.util.stream.*;
public class Test {
public static void main(String[] args) {
List<Pearson> duplicates = Arrays.asList(
new Pearson("John", "Doe"),
new Pearson("William", "Doe"),
new Pearson("Edgar", "Poe"),
new Pearson("Allan", "Poe"),
new Pearson("Don", "King")
);
List<Pearson> uniques = duplicates.stream()
// map LastName -> List<FirstName>
.collect(Collectors.groupingBy(
Pearson::getLastName,
LinkedHashMap::new, // keep order of entries
Collectors.mapping(
Pearson::getFirstName,
Collectors.toList())
)).entrySet()
.stream()
.map(e -> new Pearson(e.getValue(), e.getKey()))
.collect(Collectors.toList());
uniques.forEach(u ->
System.out.println(
String.join(" ", u.getAllFirstNames())
+ " " + u.getLastName()
));
}
}
Output
John William Doe
Edgar Allan Poe
Don King
I have following statement creating an array of array of String:
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Would it be possible to get stream as following? I tried it in Eclipse but got an error.
Stream<String,String> streamObj = Arrays.stream(strArr);
Tried to search on net but mostly results were showing to get stream from 1-D array of strings as shown below:
String[] stringArr = {"a","b","c","d"};
Stream<String> str = Arrays.stream(stringArr);
There is no feasible representation such as Stream<String, String> with the java.util.stream.Stream class since the generic implementation for it relies on a single type such as it declared to be:
public interface Stream<T> ...
You might still collect the mapping in your sub-arrays as a key-value pair in a Map<String, String> as:
Map<String, String> map = Arrays.stream(strArr)
.collect(Collectors.toMap(s -> s[0], s -> s[1]));
To wrap just the entries further without collecting them to a Map, you can create a Stream of SimpleEntry as :
Stream<AbstractMap.SimpleEntry<String, String>> entryStream = Arrays.stream(strArr)
.map(sub -> new AbstractMap.SimpleEntry<>(sub[0], sub[1]));
You can define a POJO called StringPair and map the stream.
public class PairStream {
public static void main(String[] args) {
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Arrays.stream( strArr ).map( arr -> new StringPair(arr) ).forEach( pair -> System.out.println(pair) );
}
private static class StringPair {
private final String first;
private final String second;
public StringPair(String[] array) {
this.first = array[0];
this.second = array[1];
}
#Override
public String toString() {
return "StringPair [first=" + first + ", second=" + second + "]";
}
}
}
As well as you can use Apache Commons lang Pair
public class PairStream {
public static void main(String[] args) {
String[][] strArr = {{"Jazz","80"},{"sam","90"},{"shaam","80"},{"aditya","100"}};
Arrays.stream( strArr ).map( arr -> Pair.of(arr[0],arr[1]) ).forEach( pair -> System.out.println(pair) );
}
}
I am trying to convert the below nested loop in to streams Java 8.
Each element in newself2 is a list of string - ["1 2","3 4"] needs to change to ["1","2","3","4"].
for (List<String> list : newself2) {
// cartesian = [["1 2","3 4"],["4 5","6 8"]...] list = ["1 2","3 4"]...
List<String> clearner = new ArrayList<String>();
for (String string : list) { //string = "1 3 4 5"
for (String stringElement : string.split(" ")) {
clearner.add(stringElement);
}
}
newself.add(clearner);
//[["1","2","3","4"],["4","5","6","8"]...]
}
What I have tried till now -
newself2.streams().forEach(list -> list.foreach(y -> y.split(" ")))
Now I am now sure how to add the split array in the inner for loop to a new list for x?
Any help is greatly appreciated.
Here's how I'd do it:
List<List<String>> result = newself2.stream()
.map(list -> list.stream()
.flatMap(string -> Arrays.stream(string.split(" ")))
.collect(Collectors.toList()))
.collect(Collectors.toList());
This is other solution.
Function<List<String>,List<String>> function = list->Arrays.asList(list.stream()
.reduce("",(s, s2) -> s.concat(s2.replace(" ",",")+",")).split(","));
and use this function
List<List<String>> finalResult = lists
.stream()
.map(function::apply)
.collect(Collectors.toList());
with for loop is similar to this:
List<List<String>> finalResult = new ArrayList<>();
for (List<String> list : lists) {
String acc = "";
for (String s : list) {
acc = acc.concat(s.replace(" ", ",") + ",");
}
finalResult.add(Arrays.asList(acc.split(",")));
}
I am trying to add quotes to data in a CSV file. Below is the approach i have done it. I am sure there is a simpler way using regex or other methods. Would like to know that.
public List<String> addQuotes2List(List<String> list, String delimiter){
List<String> tempList = new ArrayList<>();
String temp="", value;
Integer i=-1, j=0;
for(String s1: list){
//println("S1 - "+s1+" - "+Arrays.asList(s1.split("\\"+delimiter)) );
i++;
tempList = Arrays.asList(s1.split("\\"+delimiter));
//println(tempList);
temp="";j=0;
for(String s2:tempList){
if(j>0)
temp+=delimiter;
//println("S2 - "+s2);
temp+="\""+s2+"\"";
j++;
}
list.set(i, temp);
}
return list;
}
Input
tempList.clear();
tempList.add("Sushanth.Bobby.Lloyds");
tempList.add("Watch.a.lot.of.movies");
tempList.add("main.hobby.is.programming");
tempList.add("programming.is.dangerous.addiction.of.all");
tempList = a.addQuotes2List(tempList,".");
println("tempList - "+tempList.size());
for(String s:tempList)
println(s);
output
tempList - 4
"Sushanth"."Bobby"."Lloyds"
"Watch"."a"."lot"."of"."movies"
"main"."hobby"."is"."programming"
"programming"."is"."dangerous"."addiction"."of"."all"
Thanks,
Sushanth
if you just handle the string .
you may just replce <.> to <"."> and append <"> on starts and ends .
public List<String> addQuotes2List2(List<String> list, String delimiter) {
List<String> tempList = new ArrayList<String>();
// null check list and delimiter
String rStr = "\""+delimiter+"\"";
String rmsg = "";
for (String s1 : list) {
rmsg = s1.replace(delimiter, rStr);
rmsg = "\""+rmsg+"\"";
tempList.add(rmsg);
}
return tempList;
}
regex may no necessary here. (replace and replaceAll made by regex)
If you're using Java 8, you can use streams to make it more readable.
public List<String> addQuotes2List(List<String> list, String delimiter){
return list.stream()
.map(line -> line.split("\\"+delimiter))
.map(this::addQuotes)
.map(entries -> String.join(delimiter, entries))
.collect(Collectors.toList());
}
private List<String> addQuotes(String[] entries) {
return Arrays.stream(entries)
.map(entry -> String.format("%s", entry))
.collect(Collectors.toList());
}
I have a list which contains list of values like below
[a-xyz,b-yzx,c-aaa,d-rrr,a-qqq,b-hhh]
and i need the above list like below
[xyz,yzx,aaa,rrr,qqq,hhh]
There a several things that should be done here. First, you need to get rid of the enclosing [] so the string could be split. Then, you need to actually split it (by commas). Then, for each string, you need to remove the prefix before the -. Java 8's stream give you a pretty neat way of doing this:
List<String> result =
Arrays.stream(str.substring(1, str.length() - 1).split(","))
.map(s -> s.replaceFirst("\\w-", ""))
.collect(Collectors.toList());
EDIT:
In JDK 7 and below the solution would be similar, but you'd have to resort to using loops instead of streams:
String[] arr = str.substring(1, str.length() - 1).split(",");
List<Stirng> result = new ArrayList<>(arr.length);
for (String s : arr) {
result.add(s.replaceFirst("\\w-", ""));
}
Try this
List<String> list = Arrays.asList("a-xyz","b-yzx","c-aaa","d-rrr","a-qqq","b-hhh");
List<String> result = list.stream()
.map(s -> s.replaceFirst("^.*-", ""))
.collect(Collectors.toList());
System.out.println(result);
result:
[xyz, yzx, aaa, rrr, qqq, hhh]
Or Java7
List<String> list = Arrays.asList("a-xyz","b-yzx","c-aaa","d-rrr","a-qqq","b-hhh");
List<String> result = new ArrayList<>();
for (String s : list)
result.add(s.replaceFirst("^.*-", ""));
System.out.println(result);
call me old-fashioned
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Split {
public static void main(String[] args) {
String[] ss = {"a-xyz","b-yzx","c-aaa","d-rrr","a-qqq","b-hhh"};
List<String> ll = new ArrayList<>();
ll.addAll(Arrays.asList(ss));
List<String> result = new ArrayList<>();
for(String s:ll) {
result.add(s.split("-")[1]);
}
System.out.println(result);
}
}
gives
[xyz, yzx, aaa, rrr, qqq, hhh]
You can use same list to store final value using set method of list.
import java.util.ArrayList;
public class SplitList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("a-xyz");
list.add("b-yzx");
list.add("c-aaa");
list.add("d-rrr");
list.add("a-qqq");
list.add("b-hhh");
for(String st : list){
int index = list.indexOf(st); //get index of string
list.set(index,st.replaceFirst("\\w-", "")); //set only with required value
}
for(String st : list){
System.out.println(st);
}
}
}