Grouping and adding up BigDecimals using Java Stream API
I have a list of Income
objects. Each of them has a type
. I want to group them and sum up the amount
field.
For this case:
Income income1 = new Income();
income1.setType(IncomeType.COMMON);
income1.setAmount(BigDecimal.valueOf(1000));
Income income2 = new Income();
income2.setType(IncomeType.COMMON);
income2.setAmount(BigDecimal.valueOf(2000));
Income income3 = new Income();
income3.setType(IncomeType.MARCIN);
income3.setAmount(BigDecimal.valueOf(100));
List<Income> incomes = Arrays.asList(income1, income2, income3);
The expected output would be a map Map<IncomeType, BigDecimal>
with two elements:
<COMMON, 3000>
and <MARCIN, 100>
How to achieve it with Java Stream API?
3 answers
-
answered 2018-05-16 06:07
daniu
The grouping is done by
groupingBy
, which allows a "downstream collector" that can do the summing.incomes.stream() // to map, you say? .collect(Collectors.groupingBy(Income::getType, // add the big integers Collectors.reducing(BigDecimal.ZERO, Income::getAmount, BigDecimal::add)));
-
answered 2018-05-16 06:14
Flown
Simplest solution would be using
Collectors::toMap
including the merge function.Map<IncomeType, BigDecimal> grouping = incomes.stream() .collect(Collectors.toMap(Income::getType, Income::getAmount, BigDecimal::add));
-
answered 2018-05-16 06:24
Hadi J
Other way could be like this:
Map<IncomeType,BigDecimal> map = new HashMap<>(); incomes.forEach(income ->map.merge(income.getType(),income.getAmount(),BigDecimal::add));
See also questions close to this topic
-
Can searchResponse.getHits().getHits(); throw nullpointer exception
We are getting a nullpointerexception at searchResponse.getHits().getHits(); I'm totally new to elastic search and don't know how it works but need to analyse this issue.
Let me know if it throws nullpointerexception in any case ? If it throws how to handle this ?
-
Is it possible to disable SSL certificate checking in the amazon kinesis consumer library v2?
When developing a Kinesis Consumer using Version 2 of the Kinesis Consumer Library and overriding the Dynamo DB endpoint to a localstack endpoint the library fails to create the leasing table due to SSL handshake errors.
I can confirm that creating the table succeeds when using AWS' Dynamo DB, but as soon as I override the endpoint url to a localstack url the Dynamo DB client fails to create the lease table after multiple retries. The stack trace isn't that useful but Wireshark shows all of the SSL handshake errors so I can only assume the Amazon SDK is not accepting the localstack certificate. I cannot find any mention of how to disable certificate verification using the
software.amazon.awssdk
package.Region region = Region.of("us-east-1"); DefaultCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create(); DynamoDbAsyncClient dynamoClient = DynamoDbAsyncClient.builder() .region(region) .endpointOverride(URI.create("https://localhost:4569")) .credentialsProvider(credentialsProvider) .build();
/edit This is based off the example from Amazon found here: https://docs.aws.amazon.com/streams/latest/dev/kcl2-standard-consumer-java-example.html
-
Problem creating an OracleDataSource correctly from tomcat context.xml
In the project im working at the following problem occurs:
We use Database connections defined in our tomcat context.xml. For now this has worked without problems.
Example:
<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" logAbandoned="true" maxIdle="10" maxTotal="100" maxWaitMillis="5000" name="NAME" password="PASSWORD" removeAbandonedOnMaintenance="true" removeAbandonedTimeout="60" type="javax.sql.DataSource" url="URL" username="USERNAME" />
This type of resource definition is used in the webapp for every database connection, retreiving the datasource like this:
InitialContext ctx = new InitialContext(); DataSource dsAux = (DataSource) ctx.lookup(dbCon);
The problem begins here. Oracle queues are being used with jms (Java Message System) for a lot of processes. For this, as it is coded right now, we need an OracleDataSource that can be created having only the db url, password and username.
My question is, is it possible in any way or form to get all the data needed from the context for this type of datasource correctly? I have tried changing the datasource type without any luck, unwrapping the already created datasource to try and create an OracleDataSource, in the end, the only possible solution I have come up with is to change how database connections are saved.
-
How to create a new Map by splitting the keys of a Map <String, List<Object>> that contain duplicate names
I have a
Map
of type<String, List<Object>>
where the keys of thisMap
are names (String
) associated with anObject
that contains X and Y coordinates.Example:
Names (String) Coordinates Cord1 [[0.1,0.1,0.1],[0.2,0.3,0.4]] Cord1,Cord2 [[0.1,0.1] ,[0.4,0.5]] Cord1,Cord2,Cord3 [[0.1,0.1] ,[0.6,0.7]]
What I want to achieve is to split the names when there is a comma
,
so I can have only single names, which will also affect the coordinates and avoid repetition.Example of what I would like to achieve:
Cord1 [[0.1,0.1,0.1,0.1,0.1,0.1],[0.2,0.3,0.4,0.5,0.6,0.7]] Cord2 [[0.01,0.01,0.01,0.01] ,[0.4,0.5,0.6,0.7]] Cord3 [[0.01,0.01] ,[0.6,0.7]]
Is there a way to do this?
EDIT:
I am not very familiar with Java 8 which apparently is the most optimal way to do it, but I was experimenting with something along these lines which has not worked so far:
List<String> list = Splitter.on(',').splitToList(value); for (String element : list) { //TO-DO }
Cord Object:
public class Cord { private double X; private double Y; private String name; public Cord(double x, double y, String name) { this.X=x; this.Y=y; this.name=name; } @Override public String toString() { return "["+X+","+Y+"]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getX() { return X; } public void setX(double x) { X = x; } public double getY() { return Y; } public void setY(double y) { Y = y; } }
-
Unable to establish connection over TLS 1.2 on AIX 7.1/7.2
How to enable communication over TLS1.2 on AIX 7.1 or 7.2 with IBM JDK 1.8 latest update?
By default, the request is trying to establish a connection over TLSv1 even though TLS 1.2 is explicitly enabled on server as well as on Java 8. The openssl command throws SSL handshake error. We tried with 2 versions of OpenSSL, 1.0.1e and 1.0.2k, but same behavior.
logs:
[06:24 AM root@s822-aix01p1 /opt]: openssl s_client -tls1_2 -connect 10.225.120.125:8443 CONNECTED(00000003) 804401144:error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:s3_pkt.c:1259:SSL alert number 80 804401144:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:599: no peer certificate available No client certificate CA names sent SSL handshake has read 7 bytes and written 0 bytes New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1.2 Cipher : 0000 Session-ID: Session-ID-ctx: Master-Key: Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Start Time: 1550489753 Timeout : 7200 (sec) Verify return code: 0 (ok)
It seems there is no cipher suites on common which can work for TLS 1.2.
Also, is there any way to enable TLS 1.1 & 1.2 in AIX? I have read few articles and got to know that these are not enabled by default on AIX.
-
Why am i getting blank stage in JavaFX8, I think the maven is not loading the FXML files?
This is my pom.xml file which is not loading the fxml file in the resources as an output im just getting a blank stage (Panel) onto the screen. There might a path issue I have pasted the code please let me where I am going wrong please help me to solve this problem.
Pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.objectiveware</groupId> <artifactId>QCap</artifactId> <version>1.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <javafx.version>2.2</javafx.version> </properties> <build> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <encoding>UTF-8</encoding> <source>1.8</source> <target>1.8</target> <fork>true</fork> <executable>C:\Program Files\Java\jdk1.8.0_191\bin\javac</executable> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <goals> <goal>attached</goal> </goals> <phase>package</phase> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.objectiveware.qcap.QcapAppSingletonRunner</mainClass> </manifest> </archive> </configuration> </execution> </executions> </plugin> <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.3</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <configuration> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> <goals> <goal>copy-dependencies</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifestEntries> <JavaFX-Version>${javafx.version}+</JavaFX-Version> <Main-Class>com.objectiveware.qcap.StartCaptureTaskBar</Main-Class> <implementation-version>1.0</implementation-version> <JavaFX-Application-Class>com.objectiveware.qcap.StartCaptureTaskBar</JavaFX-Application-Class> <Class-Path>javafx-${javafx.version}.jar</Class-Path> </manifestEntries> <manifest> <addClasspath>true</addClasspath> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.6</version> <executions> <execution> <phase>package</phase> <configuration> <target> <path id="qcappath"> <pathelement path="${maven.plugin.classpath}"/> <fileset dir="${project.basedir}"> <include name="package/windows/QCap.ico"/> </fileset> </path> <taskdef name="jfxdeploy" classname="com.sun.javafx.tools.ant.DeployFXTask" classpathref="qcappath" /> <jfxdeploy width="1024" height="768" outdir="${project.build.directory}/deploy" outfile="${project.build.finalName}" nativeBundles="exe" verbose="true"> <info title="${project.name}" /> <application name="${project.name}" mainClass="com.objectiveware.qcap.StartCaptureTaskBar" /> <resources> <fileset dir="${project.build.directory}" includes="*.jar" /> <fileset dir="${project.build.directory}/dependency" includes="*.jar" /> </resources> <platform javafx="${javafx.version}+"> <jvmarg value="-Xms512m" /> <jvmarg value="-Xmx1024m" /> </platform> </jfxdeploy> </target> </configuration> <goals> <goal>run</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>com.oracle</groupId> <artifactId>ant-javafx</artifactId> <version>${javafx.version}</version> <systemPath>${java.home}/../lib/ant-javafx.jar</systemPath> <scope>system</scope> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>javafx</artifactId> <version>${javafx.version}</version> <systemPath>${java.home}/lib/ext/jfxrt.jar</systemPath> <scope>system</scope> </dependency> </dependencies> </plugin> --> </plugins> </build> <dependencies> <!-- https://mvnrepository.com/artifact/org.docx4j/docx4j --> <dependency> <groupId>org.docx4j</groupId> <artifactId>docx4j</artifactId> <version>6.0.1</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf-openpdf --> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-openpdf</artifactId> <version>9.1.16</version> </dependency> <!-- https://mvnrepository.com/artifact/com.jfoenix/jfoenix --> <dependency> <groupId>com.jfoenix</groupId> <artifactId>jfoenix</artifactId> <version>1.4.0</version> </dependency> <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform --> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>4.0.0</version> </dependency> <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna --> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>4.5.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.8.3</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.maven/maven-plugin-api --> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>javafx</artifactId> <version>${javafx.version}</version> <systemPath>${java.home}/lib/ext/jfxrt.jar</systemPath> <scope>system</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.6</version> </dependency> <dependency> <groupId>org.kordamp.bootstrapfx</groupId> <artifactId>bootstrapfx-core</artifactId> <version>0.2.4</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>11</version> </dependency> </dependencies> </project>
Java class
package com.objectiveware.qcap;
import static com.objectiveware.qcap.controllers.AppController.applicationScreenCapture; import java.awt.Desktop; import java.awt.SystemTray; import java.awt.TrayIcon; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Timer; import java.util.TimerTask; import javax.imageio.ImageIO; import javafx.application.Application; import javafx.scene.layout.BorderPane; import org.apache.commons.lang3.StringUtils; import com.objectiveware.qcap.controllers.LoginController; import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.stage.StageStyle; public class StartCaptureTaskBar { private static Timer notificationTimer = new Timer(); private static SystemTray tray; private static TrayIcon trayIcon; private Stage stage; private Stage settingsStage; private boolean authenticated; private Runnable exitCallback; private String userName; private String password; private boolean rememberChk; private boolean StartQCapAtLogin; public void createInstance(Stage stage, Runnable exitCallback) { // stores a reference to the stage. this.stage = stage; this.exitCallback = exitCallback; // instructs the javafx system not to exit implicitly when the last application // window is shut. Platform.setImplicitExit(false); // sets up the tray icon (using awt code run on the swing thread). javax.swing.SwingUtilities.invokeLater(this::addAppToTray); this.stage.setResizable(false); this.stage.initStyle(StageStyle.UTILITY); this.stage.setScene(createLoginContent()); this.stage.setTitle("Login/Setting"); this.stage.show(); } public void open() { Platform.runLater(this::showStage); } /** * Callback method invoked to notify that a user has been authenticated. Will * show the main application screen. */ public void authenticated(String sessionID) { authenticated = true; startMainPage(); } public void startMainPage() { stage.setScene(createMainPageContent()); stage.setTitle("Start Session"); if (applicationScreenCapture != null && applicationScreenCapture.isStoped()) { applicationScreenCapture.restart(); applicationScreenCapture.startHotKeysKeyboardListner(); stage.hide(); } } // TODO: will be implemented later, button will be added in main.fxml for logout public void logout() { authenticated = false; hideSettings(); stage.setScene(createLoginContent("Session expired")); if (applicationScreenCapture != null) { applicationScreenCapture.pause(); applicationScreenCapture.pauseHotKeys(); } showStage(); } private Scene createLoginContent() { return createLoginContent(""); } private Scene createLoginContent(String error) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("/gui/login.fxml")); Parent root = loader.load(); Scene scene = new Scene(root, 500, 400); //scene.getStylesheets().add("org/kordamp/bootstrapfx/bootstrapfx.css"); scene.getStylesheets().add(getClass().getResource("/stylesheets/LoginTheme.css").toExternalForm()); LoginController controller = loader.<LoginController>getController(); if (StringUtils.isNotEmpty(error)) { controller.setErrorMessage(error); } controller.initManager(this); return scene; } catch (IOException e) { e.printStackTrace(); } return null; } private Scene createMainPageContent() { try { Parent root = FXMLLoader.load(getClass().getResource("/gui/main.fxml")); Scene scene = new Scene(root); return scene; } catch (IOException e) { e.printStackTrace(); } return null; } /** * Sets up a system tray icon for the application. */ private void addAppToTray() { try { java.awt.Toolkit.getDefaultToolkit(); // app requires system tray support, just exit if there is no support. if (!java.awt.SystemTray.isSupported()) { System.out.println("No system tray support, application exiting."); Platform.exit(); } tray = java.awt.SystemTray.getSystemTray(); java.awt.Image image = ImageIO.read(getClass().getResource("/icons/screenshot.png")); trayIcon = new java.awt.TrayIcon(image); trayIcon.addActionListener(event -> Platform.runLater(this::showStage)); // if the user selects the default menu item (which includes the app name), // show the main app stage. java.awt.MenuItem openItem = new java.awt.MenuItem("Start QCap"); openItem.addActionListener(event -> Platform.runLater(this::showStage)); // the convention for tray icons seems to be to set the default icon for opening // the application stage in a bold font. java.awt.Font defaultFont = java.awt.Font.decode(null); java.awt.Font boldFont = defaultFont.deriveFont(java.awt.Font.BOLD); openItem.setFont(boldFont); java.awt.MenuItem settingsItem = new java.awt.MenuItem("Settings"); settingsItem.addActionListener(event -> Platform.runLater(this::showSettings)); java.awt.MenuItem CheckForUpdatesItem = new java.awt.MenuItem("Check for Updates"); CheckForUpdatesItem.addActionListener(event -> { try { Desktop.getDesktop().browse(new URI(Constants.CHECK_FOR_UPDATES_URL)); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }); java.awt.MenuItem helpItem = new java.awt.MenuItem("Help"); helpItem.addActionListener(event -> { try { Desktop.getDesktop().browse(new URI(Constants.HELP_URL)); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }); java.awt.MenuItem aboutUSItem = new java.awt.MenuItem("About Us"); aboutUSItem.addActionListener(event -> { try { Desktop.getDesktop().browse(new URI(Constants.ABOUT_US_URL)); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }); // to really exit the application, the user must go to the system tray icon // and select the exit option, this will shutdown JavaFX and remove the // tray icon (removing the tray icon will also shut down AWT). java.awt.MenuItem exitItem = new java.awt.MenuItem("Exit"); exitItem.addActionListener(event -> exit()); // setup the popup menu for the application. final java.awt.PopupMenu popup = new java.awt.PopupMenu(); popup.add(openItem); popup.add(settingsItem); popup.addSeparator(); popup.add(CheckForUpdatesItem); popup.add(helpItem); popup.add(aboutUSItem); popup.addSeparator(); popup.add(exitItem); trayIcon.setPopupMenu(popup); // create a timer which periodically displays a notification message. notificationTimer.schedule(new TimerTask() { @Override public void run() { javax.swing.SwingUtilities.invokeLater(() -> trayIcon.displayMessage("QCap Notifiction", "QCap app is running ", java.awt.TrayIcon.MessageType.INFO)); } }, 5 * 60 * 1000, 5 * 60 * 1000); tray.add(trayIcon); } catch (java.awt.AWTException | IOException e) { System.out.println("Unable to init system tray"); e.printStackTrace(); } } void exit() { notificationTimer.cancel(); Platform.exit(); tray.remove(trayIcon); exitCallback.run(); System.exit(0); } /** * Shows the application stage and ensures that it is brought ot the front of * all stages. */ private void showStage() { if (stage != null) { stage.show(); stage.toFront(); stage.setIconified(false); stage.setAlwaysOnTop(true); stage.setAlwaysOnTop(false); } } private void showSettings() { if (isAuthenticated()) { if (settingsStage == null) { settingsStage = new Stage(); } settingsStage.setScene(createLoginContent()); settingsStage.setTitle("Login/Settings"); settingsStage.show(); settingsStage.toFront(); settingsStage.setIconified(false); } } public void hideSettings() { if (settingsStage != null) { settingsStage.hide(); } } // public static void main(String[] args) throws IOException, // java.awt.AWTException { // launch(args); // } public void setStage(Stage stage) { this.stage = stage; } public boolean isAuthenticated() { return authenticated; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isRememberChk() { return rememberChk; } public void setRememberChk(boolean rememberChk) { this.rememberChk = rememberChk; } public boolean isStartQCapAtLogin() { return StartQCapAtLogin; } public void setStartQCapAtLogin(boolean startQCapAtLogin) { StartQCapAtLogin = startQCapAtLogin; }
}
-
Is there an elegant way to convert a Map<P, Optional<Q>> to a sparse Map<P, Q>?
Is there an elegant way to convert a
Map<P, Optional<Q>>
to a sparseMap<P, Q>
?This should work, but it's a bit meh:
Map<P,Optional<Q>> map = ...; Map<P,Q> map2 = map.entrySet() .stream().filter(e -> e.getValue().isPresent()) .collect(Collectors.toMap(e -> e.getKey(), e->e.getValue().get()));
-
Intersection between nested lists java 8 streams
I have a nested list of
Long
. for example:List<List<Long>> ids = [[1,2,3],[1,2,3,4],[2,3]];
Is there a way using streams to create a new list of items that are present in all the lists:
List<Long> result = [2,3];
-
Elegant way to overcome Unlikely argument type for equals(): Stream<String> seems to be unrelated to String
I am looking for elegant way to overcome while comparing any Wrapper object to Stream.
Github working link: https://github.com/vishwaratna/Unlikely-argument-type-for-equals-Stream-String-/commit/d803f77c923e81fe7531ecb467561ac785d7aca5
Question in reference: Filtering keys from map to list attribute in java-8
Recently i faced it while comparing member of
List
to a key of aMap
. I know there are other ways to compare without doing what i am doing but i am looking for in general casting, if it is available.List<student> stulist = Arrays.asList(new student("1", "vishwa",null), new student("3", "Ravi",null), new student("2", "Ram",null));
Map<String,String> map = new HashMap() {{ put("1","20"); put("2","30"); }};
System.out.println( stulist.stream() .filter(s->s.getId() .equals(map.entrySet() .stream() .map(Map.Entry::getKey))) .count());
My code is compiling properly but the output is coming as "0", whereas i expect output as 2.
I am sure it is due to type mismatch, but why the compiler is not throwing an error??
Warning that i am getting:
Unlikely argument type for equals(): Stream<String> seems to be unrelated to String