Writing data to a .CSV file using a Java 8 Stream - java

I am trying to output 2 collections of data to a .csv file in Java.
Collection 1 = customer names
Collection 2 = customer references
I want the .csv to present as:
Smith:839393,
Johnson:283940,
Collins:293845
My code:
private void writeDataToFile() throws IOException {
FileWriter writer = new FileWriter("src/test/resources/custData.csv");
List<String> customers = new ArrayList<>(customers);
List<String> references = new ArrayList<>(references);
String collect1 = customers.stream().collect(Collectors.joining(",\n" + ":"));
String collect2 = references.stream().collect(Collectors.joining(",\n" + ":"));
writer.write(collect1 + collect2);
writer.close();
}
My output:
Smith,
:Johnson,
:Collins839393,
:283940,
:293845
How can I achieve the desired output?

You can do this way if both lists have the same size. Use IntStream.range to iterate the lists and then map the data. Then collect joining ,\n
String res = IntStream.range(0, customers.size())
.mapToObj(i -> customers.get(i) + ":" + references.get(i))
.collect(Collectors.joining(",\n"));

Assuming both of your collections have same number of elements you can try this
String output =
IntStream.rangeClosed(0, customers.size()-1)
.boxed()
.map(i -> customers.get(i) + ":" + references.get(i))
.collect(Collectors.joining("\n"));
writer.write(output);

I assume customers and references have the same size. You can iterate between 0 and customers.size() and combine the elements of both lists:
customers.get(i) + ":" + references.get(i) + ",\n"
Try this:
String output = IntStream.range(0, customers.size()).boxed()
.map(i -> customers.get(i) + ":" + references.get(i) + ",\n").collect(Collectors.joining());

What you are trying to do is called collection zipping.
See full article here
In pure java you can do the solutions
IntStream.range(0, Math.min(customers.size(), references.size()))
.mapToObj(i -> customers.get(i) + ":" + references.get(i))
.collect(Collectors.joining(",\n"));
If you have guava you can do it bit nicer
Streams
.zip(customers.stream(), references.stream(), (customer, reference) -> customer + ":" + reference)
.collect(Collectors.joining(",\n"));

Related

How do I convert a multiple strings into a set of strings?

So I have following strings,
String a = "123, 541, 123"
String b = "527"
String c = "234, 876"
I would like to loop over these strings, split the string by "," and store it in a set of string so that I have such final output,
("123", "541", "527", "234", "876")
Any idea how I can achieve this?
I have tried splitting the string but that results in Set<String[]> and not sure how to proceed with this since I am very new to this.
First, you need to separate strings in "a" and "c" variable. For that you can you can you split() method. You can try code below and adapt it in a way that fits your needs.
Set<String> strings = new HashSet<>();
String a = "123, 541, 123";
String b = "527";
String c = "234, 876";
private void addToSet(String stringNumbers) {
for(String str : Arrays.asList(stringNumbers.split(","))) {
strings.add(str);
}
}
I would do it simply like that:
String a = "123, 541, 123";
String b = "527";
String c = "234, 876";
List<String> all = Arrays.asList((a + "," + b + "," + c).split(","));
Set<String> result = new HashSet<>();
for (String s : all) {
result.add(s.trim());
}
System.out.println(result); // [123, 541, 234, 876, 527]
But I would try to the change the situtation that you have 3 different strings in the first place. Input should be an Array of Strings, so you don't have to care, if it is 1 or 37238273 different strings.
But without knowing where you have these 3 strings from, why they are 3 variables, hard to advice how to actually optimize that.
Something like this:
List<String> all = Arrays.asList((a + ", " + b + ", " + c).split(", "));
A simple approach with Stream flat-mapping:
Set<String> result = Stream.of(a, b, c)
.map(s -> s.split(", "))
.flatMap(Arrays::stream)
.collect(Collectors.toSet());
try it plz.
Set<String> result = new HashSet<>();
for (String s : (a + "," + b + "," + c).split(",")) {
result.add(s.trim());
}
In Java 9:
import java.util.Set;
Set<String> result = Set.of("123", "541", "527", "234", "876");

How I can convert Map to String?

This is my map:
Map<String, Object> params = new HashMap<>();
params.put("topicRef", "update-123456-78925-new-u1z1w3");
params.put("parentRef", "update-123456-78925-new-u1z1w3");
Script script = new Script(ScriptType.INLINE, "painless",
String.format("ctx._source.parentRef = params.parentRef; ctx._source.topicRef = params.topicRef"),
params);
request.setScript(script);
I want to convert my map into a string but I would like to change the pattern for e.g.:
"ctx._source.key = value;ctx._source.key = value"
I want to add to key value a prefix ctx._source.key and a suffix " =" (space and equal), then I would like to separate each entry with a semicolon.
String formattedMap = params.entrySet().
stream()
.map(e -> "ctx._source." + e.getKey() + " = " + e.getValue())
.collect(Collectors.joining(","));
Try something like this:
Map<String, String> yourMap = /*...*/;
StringBuilder bob = new StringBuilder();
yourMap.forEach((key, value) -> bob.append(key).append("=").append(value).append(";"));
String result = bob.toString();
If necessary you could remove the last ; on result via String.concat().
You could stream your Map's entries, then use the map operation to map each entry to the formatted String and ultimately join each element with the collect(Collectors.joining(";")) operation.
Map<String, Object> params = new HashMap<>();
params.put("topicRef", "update-123456-78925-new-u1z1w3");
params.put("parentRef", "update-123456-78925-new-u1z1w3");
String result = params.entrySet().stream()
.map(entry -> String.format("%s%s%s%s", "ctx._source.", entry.getKey(), " =", entry.getValue()))
.collect(Collectors.joining(";"));
System.out.println(result);
Here is a link to test the code
https://www.jdoodle.com/iembed/v0/rrK
Output
String result = params.entrySet()
.stream()
.map(x -> "ctx._source." + x.getKey() + " = " + x.getValue())
.reduce((x, y) -> x + ";" + y).get();

flatMap triple nested streams

I'm trying to flatMap and get a result of list of Strings from three Lists. I somehow was able to do by the following code. The code is working but somehow I feel I have over complicated it. Can someone please give me some advice which can improve it in a better way
countries.stream()
.map(country -> titles.stream()
.map(title -> games.stream()
.map(game -> Arrays.asList(game, country + "_" + title + "_" + game))
.collect(toList()))
.collect(toList()))
.collect(toList())
.stream()
.flatMap(Collection::stream)
.flatMap(Collection::stream)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
For clarification of the logic, a traditional approach would look like:
Set<List<String>> results = new HashSet<>();
for (String country : countries) {
for (String title : titles) {
for (String game : games) {
results.add(Arrays.asList(game, country + "_" + title + "_" + game));
}
}
}
You can do this in two steps:
first create concatenation of countries and titles list:
List<String> countriesTitle = countries.stream()
.flatMap(country -> titles.stream()
.map(title -> country + "_" + title))
.collect(Collectors.toList());
then by previous result create list of concatenation country+"_"+title+"_"+game string:
Stream.concat(games.stream(),
games.stream()
.flatMap(game -> countriesTitle.stream()
.map(countryTitle -> countryTitle + "_" + game)))
.collect(Collectors.toList());
Updated answer:
games.stream()
.flatMap(game -> countries.stream()
.flatMap(country -> titles.stream()
.flatMap(title -> Stream.of(game, country + "_" + title + "_" + game))))
.collect(Collectors.toSet());

Convert Python to Java 8

I’m working in a project that use java 8, this project is about get some geographic information and work with this.
I already have done part of this work in python, and now I’m translating this part did in Python to java 8, well in Python I use this lines bellow to convert coordinates in Google format to Postgis format:
s1 = tuple(value.split(" "))
s2 = zip(s1[1::2], s1[::2])
For example:
I have a entrance like: value = "11.12345679 12.987655 11.3434454 12.1223323" and so on
The Python code above changes de entrance to:
s2 = "12.987655 11.12345679 12.1223323" and so on.
Changing the position of each coordinate pair, each entrance have thousands of coordinates.
To get the same effect with java (before java 8):
Using my knowledge of java (acquired before the java 8) I will need do that:
try {
String result = "", right = "", left = "";
String[] txt = str.split(" ");
for (int i = 0; i < txt.length; i += 2) {
right = txt[i];
left = txt[i + 1];
result += "," + left + " " + right;
}
return result.substring(1);
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
I will execute the java code above thousands of times, my question is: Java 8 has some new way to do this code above more like Python ?
My motivation to ask that question is because I came across with this news about Java 8:
List<String> someList = new ArrayList<>();
// Add some elements
someList.add("Generic (1.5)");
someList.add("Functional (8)");
// Open a stream
someList.stream()
// Turn all texts in Upper Case
.map(String::toUpperCase)
// Loop all elemnst in Upper Case
.forEach(System.out::println);
Updating:
The solution of Jean-François Savard was perfect using Java 8 like I asked, thank you so much Jean-Francois Savard
String str = "11.12345679 12.987655 11.3434454 12.1223323 11.12345679 12.987655 11.3434454 12.1223323";
String[] strs = str.split(" ");
str = IntStream.range(0, strs.length) .filter(i -> i % 2 == 0) .mapToObj(i -> strs[i + 1] + " " + strs[i]) .collect(Collectors.joining(","));
System.out.println(str);
>> 12.987655 11.12345679,12.1223323 11.3434454,12.987655 11.12345679,12.1223323 11.3434454
The solution shown by Vampire and Tukayi fit perfectly in my problem, thanks a lot guys
String str = "11.12345679 12.987655 11.3434454 12.1223323 11.12345679
12.987655 11.3434454 12.1223323";
str = str.replaceAll("([^\\s]+) ([^\\s]+)(?: |$)", ",$2 $1").substring(1);
System.out.println(str);
Define the following in your class to precompile a Regex pattern
private static final Pattern pattern = Pattern.compile("([^ ]++) ([^ ]++)(?: |$)");
Then in your method use
if ((new StringTokenizer(str, " ").countTokens() % 2) == 1) {
return null;
}
return pattern.matcher(str).replaceAll(",$2 $1").substring(1);
to get the same result as in your original code.
If you depend on using Streams why-o-ever, here a Streams solution
String[] strs = str.split(" ");
return IntStream.range(0, strs.length)
.filter(i -> i % 2 == 0)
.mapToObj(i -> strs[i + 1] + " " + strs[i])
.collect(Collectors.joining(","));
Java 8 added (among other things) Lambdas, Streams and Functional interfaces.
You can use streams to simplify looping over objects. But the syntax like you see in Python isn't the same as in java like that.

Adding the results to an arraylist

I am facing some difficulties while assigning the values in an array list. My code is :
while (answer.hasMore()) {
SearchResult rslt = (SearchResult)answer.next();
Attributes attrs = rslt.getAttributes();
System.out.println();
if (attrs.get("department") != null && attrs.get("telephonenumber") != null) {
System.out.println(attrs.get("department") + " " + attrs.get("name") + " " +
attrs.get("Description") + " " + attrs.get("mail") + " " +
attrs.get("telephonenumber")+
attrs.get("samaccountname") + attrs.get("samaccountname") );
}
I want to assign the values of attrs.get("department") + attrs.get("description")+ attrs.get("name")+attrs.get("mail") each one to an array list.
I tried to define at the beginning:
String[] name = new String[100];
and in the while loop i tried to read the name attribute, I tried to do:
name = attrs.get("name");
But it did not work. Can anyone help.
In Java, an array and an ArrayList are quite different.
String[] name_array = new String[100];
creates a fixed-length array of Strings, but
ArrayList name_list = new ArrayList();
creates a variable-length ArrayList of objects (it will grow as you add more objects).
To add an object to an ArrayList, you can use its add() method.
name_list.add("Hello");
However, with an array you need to set the object at a specific index, e.g:
name_array[23] = "Hello";
You need to read a basic tutorial on the Java language and standard library.
You cannot directly assign strings to a array made of string "references". You need to index it first. But it would be much better to actually use a list (and maybe convert it to an array later). Check out List and ArrayList in the Java documentation.
As an example:
Attributes attrs = new Attributes();
List<String> attribValues = new ArrayList<String>();
System.out.println();
if (attrs.get("department") != null
&& attrs.get("telephonenumber") != null) {
System.out
.println(attrs.get("department") + " " + attrs.get("name")
+ " " + attrs.get("Description") + " "
+ attrs.get("mail") + " "
+ attrs.get("telephonenumber")
+ attrs.get("samaccountname")
+ attrs.get("samaccountname"));
attribValues.add(attrs.get("department"));
attribValues.add(attrs.get("telephonenumber"));
}
final String[] attribArray = attribValues.toArray(new String[attribValues.size()]);
First of all define your name as String not as an array of String like this:
String name;
And then read name as:
name = attrs.getString("name");
Now coming back to your issue of populating List, I am sure you will get ready-made answers here but I suggest you to do some reading on how to create and populate a List in Java.

Categories

Resources