I am very new to streams in java 8 so my approach could be wrong.
I have 2 objects as follows
object1 {
BigDecimal amount;
Code1 code1;
Code2 code2;
Code3 code3;
String desc;
}
object2 {
BigDecimal amount;
Code1 code1;
Code2 code2;
Code3 code3;
}
So I want to collect all object1 where code1 && code2 && code3 are same and then sum the amount add it to object2 list.
I do not have a code to do it...I want to write a code that does the job
I am trying to implement something from http://docs.oracle.com/javase/tutorial/collections/interfaces/map.html
Or compute the sum of all salaries by department:
// Compute sum of salaries by department
Map<Department, Integer> totalByDept = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.summingInt(Employee::getSalary)));
Thanks to JB Nizet for pointing me in the right direction.
I had to modify my object2
public class CodeSummary {
Double amount;
CodeKey key;
//getters and setters
}
public class CodeKey {
String code1;
String code2;
String code3;
//getters and setters
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CodeKey)) return false;
CodeKey that = (CodeKey) o;
if (!code1.equals(that.code1)) return false;
if (!code2.equals(that.code2)) return false;
if (!code3.equals(that.code3)) return false;
return true;
}
#Override
public int hashCode() {
int result = code1.hashCode();
result = 31 * result + code2.hashCode();
result = 31 * result + code3.hashCode();
return result;
}
}
iterate over object1 and populate object2. Once i had my object2 (now codeSymmary) populated. i could use the method below to do the job.
Map<CodeKey, Double> summaryMap = summaries.parallelStream().
collect(Collectors.groupingBy(CodeSummary::getKey,
Collectors.summingDouble(CodeSummary::getAmount))); // summing the amount of grouped codes.
If anyone is using this as an example. then make sure you override the equal and hashcode function in your key object. else grouping will not work.
Hope this helps someone
Related
I want to create a method that calculates multiplication of an integer and a bigdecimal. I search on Google and forums, but I didn't find anything.
import java.math.BigDecimal;
private Integer quantite;
private BigDecimal prixUnit;
public Integer getQuantite() {
return quantite;
}
public void setQuantite(Integer quantite) {
this.quantite = quantite;
}
public BigDecimal getPrixUnit() {
return prixUnit;
}
public void setPrixUnit(BigDecimal prixUnit) {
this.prixUnit = prixUnit;
}
public BigDecimal methCal(BigDecimal quantite, BigDecimal prixUnit) {
this.prixUnit=prixUnit;
BigDecimal j = new BigDecimal(quantite);
this.j = quantite;
return quantite*prixUnit;
}
How can I fix this?
To multiply an integer (or byte/short/float/double) with a BigInteger (or BigDecimal), you must convert the native number to BigInteger/BigDecimal first.
// int parameter can be int or Integer
public static BigInteger multiply ( int a, BigInteger b ) {
return BigInteger.valueOf( a ).multiply( b );
}
// BigInteger <> BigDecimal
public static BigDecimal multiply ( int a, BigDecimal b ) {
return BigDecimal.valueOf( a ).multiply( b );
}
// same for add, subtract, divide, mod etc.
Note: valueOf is not the same as new, and for different reasons on BigDecimal and BigInteger.
In both cases, I recommend valueOf over new.
I see that you added your code, nice.
It doesn't work because Integer is mixed with BigDecimal, and also * does not work with BigDecimal.
If you compare it with my code, the fix should be obvious:
public BigDecimal methCal ( int quantite, BigDecimal prixUnit ) {
return BigDecimal.valueOf( quantite ).multiply( prixUnit );
}
Google definitely could have helped you, if you know what to look for:
https://docs.oracle.com/javase/9/docs/api/java/math/BigDecimal.html#BigDecimal-int-
This is one of the constructors for BigDecimal, which allows you to do the following:
BigDecimal five = BigDecimal.valueOf(5);
BigDecimal seven = BigDecimal.valueOf(2).add(five);
Seeing as you stated you wanted to multiply an int and a BigDecimal, this would be achieved as follows:
BigDecimal result = yourBigDecimal.multiply(BigDecimal.valueOf(yourInt));
And, supposing you want this result as an int:
int intResult = result.intValue();
Keep in mind that this throws away the fraction though. If you want rounding instead:
int intResult = result.round(0, RoundingMode.HALF_UP).intValue();
Try this:
import java.math.*;
public class calculator {
public static void main(String[] args) {
BigDecimal value1 = new BigDecimal("3383878445");
BigDecimal returnValue = calculation(2, value1);
System.out.println("value is:" + returnValue);
}
public static BigDecimal calculation(int no1, BigDecimal no2) {
BigDecimal value = BigDecimal.valueOf(no1).multiply(no2);
return value;
}
}
These methods from the Java API will be helpful.
public BigDecimal multiply(BigDecimal multiplicand)
Returns a BigDecimal whose value is (this × multiplicand), and whose scale is (this.scale() + multiplicand.scale()).
Parameters:
multiplicand - value to be multiplied by this BigDecimal.
Returns:
this * multiplicand
public BigDecimal(int val)
Translates an int into a BigDecimal. The scale of the BigDecimal is zero.
Parameters:
val - int value to be converted to BigDecimal.
Current code:
mRealm.where(AdditionalData.class)
.contains("checklistParticipants.email", a#a.com, Case.INSENSITIVE)
.equalTo("checklistParticipants.type", 0)
.findAll();
which returns me result of similar to ANY record.
I want to check in nested query, only return record if and if both condition fulfilled. likewise in nested query, record email must be a#a.com and type=0
i tried below approach but ended up in same result.
mRealm.where(AdditionalData.class)
.contains("checklistParticipants.email",a#a.com, Case.INSENSITIVE)
.findAll()
.where()
.equalTo("checklistParticipants.type", 0)
.findAll();
Below screenshot shows 2 child items,
email= a#a.com & type = 1
email= x#x.com & type = 0
Realm checking for both value in either-or approach.
Also tried:
mRealm.where(AdditionalData.class)
.equalTo("checklistParticipants.email",a#a.com, Case.INSENSITIVE)
.and()
.equalTo("checklistParticipants.type", 0)
.findAll()
classpath "io.realm:realm-gradle-plugin:5.8.0"
UPDATE
class AdditionalData {
String name;
RealmList<ChecklistParticipants> checklistParticipants;
}
class ChecklistParticipants{
String email;
String type;
String field3;
}
as #EpicPandaForce said you need to use LinkingObjects
class AdditionalData {
String name;
#LinkingObjects(ChecklistParticipants.rlAdditionalData)
final RealmResults<ChecklistParticipants> linkedChecklistParticipants = null;
public RealmResults<RealmDocumentLines> getLinkedChecklistParticipants() {
return linkedChecklistParticipants ;
}
}
ChecklistParticipants
class ChecklistParticipants{
String email;
String type;
String field3;
AdditionalData rlAdditionalData;
public AdditionalData getAdditionalData() {
return rlAdditionalData;
}
public void setAdditionalData(AdditionalData additionalData) {
this.rlAdditionalData = additionalData ;
}
}
Then query
RealmResult<ChecklistParticipants> result = mRealm.where(ChecklistParticipants.class)
.contains("email", a#a.com, Case.INSENSITIVE)
.equalTo("type", 0)
.findAll();
then loop over the result and use getAdditionalData() from each item
I'm new to java 8 programming and would like to know what is the best way to rewrite the below using streams()/lambda's.
class Person {
String name;
int age;
...
}
public boolean checkPersonAboveAge(List<Person> persons, int age) {
for (Person person : persons) {
if (person.age > age) {
return true;
}
}
return false;
}
So far i tried:
public boolean checkPersonAboveAge(List<Person> persons, int age) {
Person p = persons.stream().filter(p -> p.age > age).findAny().orElse(null);
if (p != null) {
return true;
}
return false;
}
I read that with lamdba's the readability of code would improve, but looking at this example either i'm not using this feature right or missing something.
Your current stream attempt does indeed work, but it's an uncommon and not the best way to go about it.
You create an Optional object that you immediately throw away.
The code is not as compact as it can be.
Instead, utilise the anyMatch method which does exactly what you're trying to achieve.
return persons.stream().anyMatch(p -> p.age > age);
Given a directed graph with
A root node
Some leaves nodes
Multiple nodes can be connected to the same node
Cycles can exist
We need to print all the paths from the root node to all the leaves nodes. This is the closest question I got to this problem
Find all paths between two graph nodes
If you actually care about ordering your paths from shortest path to longest path then it would be far better to use a modified A* or Dijkstra Algorithm. With a slight modification the algorithm will return as many of the possible paths as you want in order of shortest path first. So if what you really want are all possible paths ordered from shortest to longest then this is the way to go. The code I suggested above would be much slower than it needs to be if you care about ordering from shortest to longest, not to mention would take up more space then you'd want in order to store every possible path at once.
If you want an A* based implementation capable of returning all paths ordered from the shortest to the longest, the following will accomplish that. It has several advantages. First off it is efficient at sorting from shortest to longest. Also it computes each additional path only when needed, so if you stop early because you dont need every single path you save some processing time. It also reuses data for subsequent paths each time it calculates the next path so it is more efficient. Finally if you find some desired path you can abort early saving some computation time. Overall this should be the most efficient algorithm if you care about sorting by path length.
import java.util.*;
public class AstarSearch {
private final Map<Integer, Set<Neighbor>> adjacency;
private final int destination;
private final NavigableSet<Step> pending = new TreeSet<>();
public AstarSearch(Map<Integer, Set<Neighbor>> adjacency, int source, int destination) {
this.adjacency = adjacency;
this.destination = destination;
this.pending.add(new Step(source, null, 0));
}
public List<Integer> nextShortestPath() {
Step current = this.pending.pollFirst();
while( current != null) {
if( current.getId() == this.destination )
return current.generatePath();
for (Neighbor neighbor : this.adjacency.get(current.id)) {
if(!current.seen(neighbor.getId())) {
final Step nextStep = new Step(neighbor.getId(), current, current.cost + neighbor.cost + predictCost(neighbor.id, this.destination));
this.pending.add(nextStep);
}
}
current = this.pending.pollFirst();
}
return null;
}
protected int predictCost(int source, int destination) {
return 0; //Behaves identical to Dijkstra's algorithm, override to make it A*
}
private static class Step implements Comparable<Step> {
final int id;
final Step parent;
final int cost;
public Step(int id, Step parent, int cost) {
this.id = id;
this.parent = parent;
this.cost = cost;
}
public int getId() {
return id;
}
public Step getParent() {
return parent;
}
public int getCost() {
return cost;
}
public boolean seen(int node) {
if(this.id == node)
return true;
else if(parent == null)
return false;
else
return this.parent.seen(node);
}
public List<Integer> generatePath() {
final List<Integer> path;
if(this.parent != null)
path = this.parent.generatePath();
else
path = new ArrayList<>();
path.add(this.id);
return path;
}
#Override
public int compareTo(Step step) {
if(step == null)
return 1;
if( this.cost != step.cost)
return Integer.compare(this.cost, step.cost);
if( this.id != step.id )
return Integer.compare(this.id, step.id);
if( this.parent != null )
this.parent.compareTo(step.parent);
if(step.parent == null)
return 0;
return -1;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Step step = (Step) o;
return id == step.id &&
cost == step.cost &&
Objects.equals(parent, step.parent);
}
#Override
public int hashCode() {
return Objects.hash(id, parent, cost);
}
}
/*******************************************************
* Everything below here just sets up your adjacency *
* It will just be helpful for you to be able to test *
* It isnt part of the actual A* search algorithm *
********************************************************/
private static class Neighbor {
final int id;
final int cost;
public Neighbor(int id, int cost) {
this.id = id;
this.cost = cost;
}
public int getId() {
return id;
}
public int getCost() {
return cost;
}
}
public static void main(String[] args) {
final Map<Integer, Set<Neighbor>> adjacency = createAdjacency();
final AstarSearch search = new AstarSearch(adjacency, 1, 4);
System.out.println("printing all paths from shortest to longest...");
List<Integer> path = search.nextShortestPath();
while(path != null) {
System.out.println(path);
path = search.nextShortestPath();
}
}
private static Map<Integer, Set<Neighbor>> createAdjacency() {
final Map<Integer, Set<Neighbor>> adjacency = new HashMap<>();
//This sets up the adjacencies. In this case all adjacencies have a cost of 1, but they dont need to.
addAdjacency(adjacency, 1,2,1,5,1); //{1 | 2,5}
addAdjacency(adjacency, 2,1,1,3,1,4,1,5,1); //{2 | 1,3,4,5}
addAdjacency(adjacency, 3,2,1,5,1); //{3 | 2,5}
addAdjacency(adjacency, 4,2,1); //{4 | 2}
addAdjacency(adjacency, 5,1,1,2,1,3,1); //{5 | 1,2,3}
return Collections.unmodifiableMap(adjacency);
}
private static void addAdjacency(Map<Integer, Set<Neighbor>> adjacency, int source, Integer... dests) {
if( dests.length % 2 != 0)
throw new IllegalArgumentException("dests must have an equal number of arguments, each pair is the id and cost for that traversal");
final Set<Neighbor> destinations = new HashSet<>();
for(int i = 0; i < dests.length; i+=2)
destinations.add(new Neighbor(dests[i], dests[i+1]));
adjacency.put(source, Collections.unmodifiableSet(destinations));
}
}
The output from the above code is the following:
[1, 2, 4]
[1, 5, 2, 4]
[1, 5, 3, 2, 4]
Notice that each time you call nextShortestPath() it generates the next shortest path for you on demand. It only calculates the extra steps needed and doesnt traverse any old paths twice. Moreover if you decide you dont need all the paths and end execution early you've saved yourself considerable computation time. You only compute up to the number of paths you need and no more.
Finally it should be noted that the A* and Dijkstra algorithms do have some minor limitations, though I dont think it would effect you. Namely it will not work right on a graph that has negative weights.
Here is a link to JDoodle where you can run the code yourself in the browser and see it working. You can also change around the graph to show it works on other graphs as well: http://jdoodle.com/a/ukx
I have declared my c# application constant this way:
public class Constant
public struct profession
{
public const string STUDENT = "Student";
public const string WORKING_PROFESSIONAL = "Working Professional";
public const string OTHERS = "Others";
}
public struct gender
{
public const string MALE = "M";
public const string FEMALE = "F";
}
}
My validation function:
public static bool isWithinAllowedSelection(string strValueToCheck, object constantClass)
{
//convert object to struct
//loop thru all const in struct
//if strValueToCheck matches any of the value in struct, return true
//end of loop
//return false
}
During runtime, I will like pass in the user inputted value and the struct to check if the value exist in the struct. The struct can be profession and gender. How can I achieve it?
Example:
if(!isWithinAllowedSelection(strInput,Constant.profession)){
response.write("invalid profession");
}
if(!isWithinAllowedSelection(strInput,Constant.gender)){
response.write("invalid gender");
}
You probably want to use enums, not structs with constants.
Enums gives you a lot of possibilities, it is not so hard to use its string values to save it to the database etc.
public enum Profession
{
Student,
WorkingProfessional,
Others
}
And now:
To check existence of value in Profession by value's name:
var result = Enum.IsDefined(typeof(Profession), "Retired"));
// result == false
To get value of an enum as a string:
var result = Enum.GetName(typeof(Profession), Profession.Student));
// result == "Student"
If you really can't avoid using value names with whitespaces or other special characters, you can use DescriptionAttribute:
public enum Profession
{
Student,
[Description("Working Professional")] WorkingProfessional,
[Description("All others...")] Others
}
And now, to get description from Profession value you can use this code (implemented here as an extension method):
public static string Description(this Enum e)
{
var members = e.GetType().GetMember(e.ToString());
if (members != null && members.Length != 0)
{
var attrs = members.First()
.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length != 0)
return ((DescriptionAttribute) attrs.First()).Description;
}
return e.ToString();
}
This method fetches description defined in attribute and if there's none, returns value name. Usage:
var e = Profession.WorkingProfessional;
var result = e.Description();
// result == "Working Professional";