java8 changing from imperative to functional - java

following is my the imperative style of code
for (int i = 1; i <= sundayOpenAreas.size(); i++) {
String area = sundayOpenAreas.get(i - 1);
String postcode = "XX" + i + " 1AA";
boolean sundayDeliveryAvailable = sundayDeliveryAvailable(area, postcode);
Assert.assertTrue(sundayDeliveryAvailable, area + " should accept deliveries on Sunday to " + postcode + "!");
System.out.println(area + ", " + postcode);
}
would like to convert to functional style java8 streams , and following is what tried so far
IntStream.range(0, sundayOpenAreas.size())
.forEach(
idx -> {
sundayOpenAreas.stream()
.map(x -> "XX" + idx + "".concat("1AA"))
//Struck here on how to proceed
//System.out.println(abc);
});
where sundayOpenAreas is List<String>

First I think you should stick to your imperative approach, because you need multiple variables in the pipeline.
I would give this a try:
IntStream.range(0, sundayOpenAreas.size())
.mapToObj(i -> new String[] { sundayOpenAreas.get(i), "XX" + i + " 1AA" })
.peek(s -> Assert.assertTrue(sundayDeliveryAvailable(s[0], s[1]),
s[0] + " should accept deliveries on Sunday to " + s[1] + "!"))
.forEachOrdered(s -> System.out.println(s[0] + ", " + s[1]));

Try this:
IntStream.range(0, sundayOpenAreas.size())
.forEach(idx -> {
sundayOpenAreas.stream()
.map(x -> "XX" + idx + "".concat("1AA"))
.filter(x -> sundayDeliveryAvailable(sundayOpenAreas.get(idx), x)).forEach(System.out::println);
});

Here is the code which you can try:
IntStream.of(sundayOpenAreas.size())
.filter(i -> {
String postcode = "XX" + i + " 1AA";
return sundayDeliveryAvailable(String.valueOf(i), postcode);
})
.forEach(System.out::println);

Related

Influx DB Java how to show tags associated with field

I have a question on accessing tag using Java.
Here is a query that works great in the UI, with the results shown in the image below.
from(bucket: "events")
|> range(start: -3h)
|> filter(fn: (r) => r["_measurement"] == "NORCA-SYSTEM-TIMESERIES")
|> filter(fn: (r) => r["_field"] == "objectCount" or r["_field"] == "norcaErrorCount")
|> aggregateWindow(every: 1m, fn: sum, createEmpty: false)
|> yield(name: "sum")
From the above, you can see it returns results from two systems for two variables
Here is the Java code which executes the same query:
#Override
public List<INorcaTotalsSystemDateDTO> norcaInfluxSystemTotalsByTimeUnit
(String systemName,
String org,
String bucket,
String cacheDatabase,
String groupByTimeUnit,
String startFromTimeUnit) {
String token = NorcaInfluxUtilsService.getInfluxToken();
String host = "http://localhost:8086";
LOG.info("running influx client");
InfluxDBClient client = NorcaInfluxUtilsService.getInfluxClient(host, token, org, bucket);
Map<LocalDateTime, INorcaTotalsSystemDateDTO> dtoMap = new HashMap<>();
Long norcaErrors = null;
Long objectCount = null;
String query = null;
if (!systemName.equalsIgnoreCase("all")) {
query = "from(bucket: \"events\")" +
" |> range(start: "
+ startFromTimeUnit + ")"
+ " |> filter(fn: (r) => r[\"_measurement\"] == \"NORCA-SYSTEM-TIMESERIES\") "
+ " |> filter(fn: (r) => r[\"System\"] == \""
+ systemName
+ "\") "
+ " |> filter(fn: (r) => r[\"_field\"] == \"objectCount\" or r[\"_field\"] == \"norcaErrorCount\") "
+ " |> aggregateWindow(every: "
+ groupByTimeUnit
+ ", fn: sum, createEmpty: false) "
+ " |> yield(name: \"sum\")";
}
else {
query = "from(bucket: \"events\")\r\n" +
" |> range(start: -3h)\r\n" +
" |> filter(fn: (r) => r[\"_measurement\"] == \"NORCA-SYSTEM-TIMESERIES\")\r\n" +
" |> filter(fn: (r) => r[\"_field\"] == \"objectCount\" or r[\"_field\"] == \"norcaErrorCount\")\r\n" +
" |> aggregateWindow(every: 1m, fn: sum, createEmpty: false)\r\n" +
" |> yield(name: \"sum\")";
}
List<FluxTable> tables = client.getQueryApi().query(query, org);
LOG.info("read from influx");
for (FluxTable table : tables) {
for (FluxRecord record : table.getRecords()) {
LOG.error(record.getTime() + " " + record.getMeasurement() + " " + record.getField() + " " + record.getValue());
// System.out.println(record.getTime() + " " + record.getMeasurement() + " " + record.getField() + " " + record.getValue());
Instant instant = record.getTime();
// ZoneId zone = ZoneId.of("UTC");
ZoneId zone = ZoneId.systemDefault();
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
INorcaTotalsSystemDateDTO currentDTO = dtoMap.get(localDateTime);
if (currentDTO == null) {
currentDTO = new NorcaTotalsSystemDateDTO();
dtoMap.put(localDateTime, currentDTO);
Map<String, Object> tempMap = null;
tempMap = record.getValues();
for (Map.Entry<String, Object> entry : tempMap.entrySet())
{
System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
}
currentDTO.setSystemName((String)tempMap.get("System"));
currentDTO.setBarcodeType((String)tempMap.get("barcodeType"));
}
else {
LOG.info("current DTO was found! " + localDateTime);
}
String formatted = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss").format(localDateTime);
currentDTO.setScanDate(formatted);
if (record.getField().equalsIgnoreCase("objectCount")) {
objectCount = (Long) record.getValue();
currentDTO.setTotalFeatures((objectCount.intValue()));
}
if (record.getField().equalsIgnoreCase("norcaErrorCount")) {
norcaErrors = (Long) record.getValue();
currentDTO.setNonZeroFeatures(norcaErrors.intValue());
}
} // checked all rows
}
When the systemName is "all", it executes the second query
query = "from(bucket: \"events\")\r\n" +
" |> range(start: -3h)\r\n" +
" |> filter(fn: (r) => r[\"_measurement\"] == \"NORCA-SYSTEM-TIMESERIES\")\r\n" +
" |> filter(fn: (r) => r[\"_field\"] == \"objectCount\" or r[\"_field\"] == \"norcaErrorCount\")\r\n" +
" |> aggregateWindow(every: 1m, fn: sum, createEmpty: false)\r\n" +
" |> yield(name: \"sum\")";
When I try to access the tags with this code (as shown above)
for (Map.Entry<String, Object> entry : tempMap.entrySet())
{
System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
}
It only prints out one of the four lines - System "01" and barcode "r"
There should be four, as shown in the graph
How can I see all the tags?
Never mind. It turns out a separate row can have exactly the same date but different tags. Maybe rows can actually be though of as columns in a relational db?

String return value in recursive function in java

So I'm practicing java currently, I'm a beginner and I try to explain all the examples that I code so I can understand how and why things are like that. I understand the concept of recursion but I came across this problem when I tried to explain this code:
import java.util.Scanner;
public class JavaExample {
public static void main(String[] args) {
String str;
System.out.println("Enter your username: ");
Scanner scanner = new Scanner(System.in);
str = scanner.nextLine();
scanner.close();
String reversed = reverseString(str);
System.out.println("The reversed string is: " + reversed);
}
public static String reverseString(String str)
{
if (str.isEmpty())
return str;
//Calling Function Recursively
return reverseString(str.substring(1)) + str.charAt(0);
}
}
With my knowledge so far about recursion, I tried to explain it like this.
Let's have for example a string "Petar":
reverseString(etar)+P
reverseString((tar)+etar)+P
reverseString((ar)+tar+etar)+P
reverseString((r)+ar+tar+etar)+P
-----------------------------------
r+ar+tar+etar+P
I noticed that the right answer is the first character from every individual piece, so I must be close.
Thank you for your time and I'm sorry if I didn't express myself clearly, I'm from Europe (sry bad inglish).
You doing good for first line reverseString(etar)+P you keep at the end only the *first char**, just do the same for next lines
put first char at the end
send the rest to the method
reverseString(etar)+P
reverseString(tar) +e+P
reverseString(ar) +t+e+P
reverseString(r) +a+t+e+P
reverseString('') +r+a+t+e+P // stops when empty string is passed
You got the first call right but the others were a bit off. In each recursive call you return the the string with the first character at the end instead of the begining. Thus, the recursion looks something like this:
reverseString("Petar")
return reverseString("etar") + "P"
return reverseString("tar") + "e"
return reverseString("ar") + "t"
return reverseString("r") + "a"
return reverseString("") + "r"
return ""
So the function will return: (((((("")+"r")+"a")+"t")+"e")+"P"), which is "rateP".
It should become clear when start with the simplest possible example: the empty string and string of size 1. Then substituting arguments of each call, to make it more obvious:
// string.isEmpty() is true, so the empty string is returned immediately
reverse("") -> ""
reverse("a") -> reverse("") + 'a' -> ("") + 'a' -> "a"
These are the trivial examples, let's try it with longer strings:
reverse("ab") -> reverse("b") + 'a'
reverse("abc") -> reverse("bc") + 'a'
-> (reverse("c") + 'b') + 'a'
-> ((reverse("") + 'c') + 'b') + 'a'
-> ((("") + 'c') + 'b') + 'a'
-> "cba"
The general pattern should be clear now. For the sake of completeness, let's manually "unroll" the recursive calls for a 4 character string:
reverse("abcd") -> reverse("bcd") + 'a'
-> (reverse("cd") + 'b') + 'a'
-> ((reverse("d") + 'c') + 'b') + 'a'
-> (((reverse("") + 'd') + 'c') + 'b') + 'a'
-> (((("") + 'd') + 'c') + 'b') + 'a'
-> "dcba"
It works like this:
reverseString("Peter") =
reverseString("eter") + P =
(reverseString("ter") + e) + P =
((reverseString("er") + t) + e) + P =
(((reverseString("r") + e) + t) + e) + P =
((((reverseString("") + r) + e) + t) + e) + P =
(((("" + r) + e) + t) + e) + P =
((((r) + e) + t) + e) + P =
(((r + e) + t) + e) + P =
(((re) + t) + e) + P =
((re + t) + e) + P =
((ret) + e) + P =
(ret + e) + P =
(rete) + P =
rete + P =
reteP
On your example when your function reaches only one character like
Peter when it becomes only "P"
and the string is not empty you call
substring(1)
Which calls an index out of the range while the string only have P on index 0 and none on index 1
You have to put a base case that checks if the string length is equal to 1 or less

Print all characters from ArrayList after each other

I have this ArrayList
ArrayList<Character> wrongLetters;
And this syso
System.out.println("Number of errors: " + wrongLetters.size() + " (" + String.join("", String.valueOf(wrongLetters)) + ")");
It now prints like this
Number of errors: 9 ([X, M, S, K, B, Q, L, I, U])
But how can I make it like this
Number of errors: 9 (XMSKBQLIU)
Java 8 or later:
final String result = wrongLetters.stream().map(String::valueOf).collect(Collectors.joining());
System.out.println("Number of errors: " + wrongLetters.size() + " (" + result + ")");
You can use wrongLetters.forEach(System.out::print); in Java 8
You can do it by this way using Java 8
System.out.println(wrongLetters.stream().map(x -> x.toString()).collect(Collectors.joining()));
Stupid answer (just remove non-alphanumerics):
System.out.println("Number of errors: " + wrongLetters.size() + " (" + String.join("", String.valueOf(wrongLetters).replaceAll("[^A-Za-z0-9]", ""))+ ")");
One more for Java 8+:
StringJoiner joiner = new StringJoiner("");
wrongLetters.stream().forEach(err -> joiner.add(String.valueOf(err)));
System.out.println("Number of errors: " + wrongLetters.size() + " (" + joiner + ")");
No Java 8 (using StringBuilder):
StringBuilder sb = new StringBuilder(" (");
for (Character character : wrongLetters) {
sb.append(character);
}
sb.append(")");
System.out.println("Number of errors: " + wrongLetters.size() + sb.toString());
String.valueOf(wrongLetters) calls toString() on array of characters thats why it look likt this. Join is called only for one String here [X, M, S, K, B, Q, L, I, U].
You have to change ArrayList to String. Check this -> Converting ArrayList of Characters to a String?
make a string from the arraylist of the characters
String str = "";
for (Character c : wrongLetters) {
str += c;
}
then :
System.out.println("Number of errors: " + wrongLetters.size() + " (" + String.join("", str) + ")");
or make a string builder :
StringBuilder stringBuilder= new StringBuilder(wrongLetters.size());
for (Character c : wrongLetters) {
stringBuilder.append(c);
}
then:
System.out.println("Number of errors: " + wrongLetters.size() + " (" + String.join("", stringBuilder.toString()) + ")");

Integer arguments being interpreted as String arguments in Java [duplicate]

This question already has answers here:
Java: sum of two integers being printed as concatenation of the two
(10 answers)
Closed 5 years ago.
Code:
class Foo
{
public static void main(String[] args)
{
int x[] = new int[5];
for(int i=0;i<5;i++)
x[i]=i*i;
for(int i=0;i<5;i++)
{
System.out.println("Value #" + i+1 + " = " + x[i]);
}
}
}
The Output:
tk#insomniac-tk:~$ java Foo
Value #01 = 0
Value #11 = 1
Value #21 = 4
Value #31 = 9
Value #41 = 16
So, what's going on here? Where am I messing up my java code? I mean why is it that in Java, the i+1 means literally i concat 1?
public class Foo
{
public static void main(String[] args)
{
int x[] = new int[5];
for(int i=0;i<5;i++)
x[i]=i*i;
for(int i=0;i<5;i++)
{
System.out.println("Value # " + (i+1) + " = " + x[i]);
}
}
}
try this
In Strings the + operator is used for concatenate, so because you did not specidy any parenthesis, your i and 1 are also concatentate, you need to use parenthesis to explicitly tell that they to be sum together :
for (int i = 0; i < 5; i++) {
System.out.println("Value #" + (i + 1) + " = " + x[i]);
}
To get :
Value #1 = 0
Value #2 = 1
Value #3 = 4
Value #4 = 9
Value #5 = 16
Next to that, another way using IntStream, which will do same :
IntStream.range(0, 5)
.mapToObj(i -> "Value #" + (i + 1) + " = " + (i * i))
.forEach(System.out::println);
The + means something like concat, if you want the expression to be evaluated put it into brackets
(i + 1) not i + 1
This line:
System.out.println("Value #" + i+1 + " = " + x[i]);
And in particular
"Value #" + i+1 + " = " + x[i]
Is syntactic sugar for the following code:
new StringBuffer().append("Value #")
.append(i)
.append(1)
.append(" = ")
.append(x[i])
.toString();
What you want is this:
"Value #" + (i+1) + " = " + x[i]
Which would translate to
new StringBuffer().append("Value #")
.append(i+1)
.append(" = ")
.append(x[i])
.toString();
Because in this case, Java append i to your String, then 1 to your String.
To evaluate the value first (and produce the result you are expecting here), you have to inform Java that you want to evaluate the value before it is appended, using parenthesis:
System.out.println("Value #" + (i+1) + " = " + x[i]);
Output
Value #1 = 0
Value #2 = 1
Value #3 = 4
Value #4 = 9
Value #5 = 16
The key reason the Java and C++ programs differ is because the operators used are different:
System.out.println("Value #" + i+1 + " = " + x[i]); // Java
cout << "Value # " << i + 1 << " = " << x[i] << endl; // C++
The + operator has a higher precedence and hence the addition is done before the overloaded << operator.
In the Java version it is all +s and so they are all evaluated left to right.
problem is in system.out.println("");,where all integers will concatinate into string when added using(+) with a string variable .Try different code for different operations with integer and string variables.
You cannot simply add an integer into a string. You must convert an integer to a string with Integer.toString(int),then add the returned value to the string.

How do I call map() on an IntStream and return a different type?

I want to do this:
IntStream.range(0, fileNames.size())
.map(i -> "mvn deploy:deploy-file" +
" -DrepositoryId=" + REPO_ID +
" -Durl=" + REPO_URL +
" -Dfile=" + LIBS + fileNames.get(i) +
" -DgroupId=" + GROUP_ID +
" -DartifactId=" + artifactName.get(i) +
" -Dversion=" + versionNumbers.get(i) +
" -DgeneratePom=true;")
.collect(Collectors.toList());
But this doesn't compile because map() passes in an int and returns an int. How do I map from int to String?
PS: Is there a more idiomatic way to write this code?
IntStream has a mapToObj method for this. With its generics, no need to cast, either:
IntStream.range(0, fileNames.size())
.mapToObj(i -> "mvn deploy:deploy-file" +
" -DrepositoryId=" + REPO_ID +
" -Durl=" + REPO_URL +
" -Dfile=" + LIBS + fileNames.get(i) +
" -DgroupId=" + GROUP_ID +
" -DartifactId=" + artifactName.get(i) +
" -Dversion=" + versionNumbers.get(i) +
" -DgeneratePom=true")
.map(s -> s + ";")
.collect(Collectors.toList());

Categories