Java: Multiply two list which are Stream<BigDecimal> - enums

I know my Question is a little for beginners, but in Internet I didn't find Answer, So It's good to have,
I have a list which contain two value, first an Enum Type, second a big decimal Number. In my Enum Class, I have also two values related to each Enum, the first value is a string and the second is a BigDecimal.
Enum:
private enum myEnumClass {
BMW("Karl Rapp", new BigDecimal("1916")), BENZ("Carl Benz", new BigDecimal("1926")),
private String founder;
private BigDecimal yearOfFoundation;
List:
List<CarDetails> numberOfcars = new ArrayList<>();
numberOfcars.add(new CarDetails(BMW, new BigDecimal("3")));
CarDetails.add(new Receipt(BENZ, new BigDecimal("5")));
CarDetails Class:
class CarDetails {
myEnumClass carCompany;
BigDecimal amountOfCar;
I want to multiply yearOfFundation to numberOfCar for each company, so like:
for BMW=1916*3;
for BENZ= 1926*5;
and then plus them: (1916*3)(1926*5);
I want to use Stream() I think it might be possible, but the problem is when I use stream I get this Datatyp: Stram, which not Allows me to use: BigDecimal.multiply(BigDecimal).
any idea how can I write is correctly?
Thanks a lot!

Using stream and reduce, You could do something like this
BigDecimal res = numberOfcars
.stream()
.reduce(
BigDecimal.ZERO,
(BigDecimal acc, CarDetails c) -> acc.add(
c.getAmountOfCar().multiply(c.getCarCompany().getYearOfFoundation())
),
BigDecimal::add
);
Demo

Related

How to work inline with custom IEqualityComparer<T> parameters

Several time I needed to call linq distincts from different IEnumerables.
These distincts often need criteria that I use just once through the software.
I found really annoying the constraint to create a class that implements the IEqualityComparer with the codebase to perform the distinct, so I thought to cover the gap creating a generic class that allows to point to a lambda expression passed as a parameter of the distinct.
In order to pass a custom IEqualityComparer parameters I developed the following class:
public class InlineComparer<T>
{
private class LambdaBasedComparer : IEqualityComparer<T>
{
public LambdaBasedComparer(Func<T, int> getHashCode)
{
fGetHashCode = getHashCode;
}
public bool Equals(T x, T y)
{
return x?.GetHashCode() == y?.GetHashCode();
}
private Func<T, int> fGetHashCode { get; set; }
public int GetHashCode(T obj)
{
return fGetHashCode(obj);
}
}
public static IEqualityComparer<T> GetComparer(Func<T, int> getHashCode)
{
return new LambdaBasedComparer(getHashCode);
}
}
What do you think about it? I hope it may be helpful!
Of course, a complete implementation of this helper makes use of this class into an extension method similar to "IEnumerable.Distinct(Func getHashCode)", but I wanted to highlight the possibility to work with lambdas to pass the distinct code.
Your equality comparer will declare two objects to be equal if they return the same value for GetHashCode(). Of course, when defining your own Equality comparer you are free to define the concept of equality any way you want, as long as your equality is reflexive, symmetric and transitive (x==x; if x==y then y==x; if x==y and y==x, then x==z).
Your equality comparer fits these rules, so you can use it.
However! Will it be a useful comparer?
You want to use a special equality comparer instead of the default equality comparer because you want some special definition of (un)equality of two objects.
Normally, during your design process you should first define equality of your objects. If you've done that and you want to use your LambdaBasedComparer you'll have to create a Hash Function that will return different values for different objects.
Normally hash functions have one requirement: two equal objects should return the same hash value. There is no requirement upon two different objects.
There are only Int32.MaxValue different Hash values, so if you've designed a class with more than this value possible unequal instances you can't use your comparer. An easy example: try to create a LambdaBasedComparer<long> that uses normal equality.
But even if your class can only create half of the Int32.MaxValue instances, it will be very difficult to create a proper hash function that will generate unique hash values for different objects.
Finally your equality will not be very intuitive if you use it to compare derived classes. Consider class Person and derived classes Employee and Customer.
IEqualityComparer<Person> personComparer = new LambdBasedComparer<Person>(...);
Person p = new Person(...);
Person e = new Employee(...);
Person c = new Customer(...);
Now I can say that a certain Person who isn't an Employee can equal one of your Employees. But would you ever say that Employees will equal Customers?
Summarized: you think that you have a simple solution for your comparers, but it will be very difficult to create a proper hash function for your definition of equality, and it will probably be even more difficult to test this hash function

Creating a stream of booleans from a boolean array? [duplicate]

There is no nice way to convert given boolean[] foo array into stream in Java-8 in one statement, or I am missing something?
(I will not ask why?, but it is really incomprehensible: why not add stream support for all primitive types?)
Hint: Arrays.stream(foo) will not work, there is no such method for boolean[] type.
Given boolean[] foo use
Stream<Boolean> stream = IntStream.range(0, foo.length)
.mapToObj(idx -> foo[idx]);
Note that every boolean value will be boxed, but it's usually not a big problem as boxing for boolean does not allocate additional memory (just uses one of predefined values - Boolean.TRUE or Boolean.FALSE).
You can use Guava's Booleans class:
Stream<Boolean> stream = Booleans.asList(foo).stream();
This is a pretty efficient way because Booleans.asList returns a wrapper for the array and does not make any copies.
of course you could create a stream directly
Stream.Builder<Boolean> builder = Stream.builder();
for (int i = 0; i < foo.length; i++)
builder.add(foo[i]);
Stream<Boolean> stream = builder.build();
…or by wrapping an AbstractList around foo
Stream<Boolean> stream = new AbstractList<Boolean>() {
public Boolean get(int index) {return (foo[index]);}
public int size() {return foo.length;}
}.stream();
Skimming through the early access JavaDoc (ie. java.base module) of the newest java-15, there is still no neat way to make the primitive boolean array work with Stream API together well. There is no new feature in the API with treating a primitive boolean array since java-8.
Note that there exist IntStream, DoubleStream and LongStream, but nothing like BooleanStream that would represent of a variation of a sequence of primitive booleans. Also the overloaded methods of Stream are Stream::mapToInt, Stream::mapToDouble and Stream::mapToLong, but not Stream::mapToBoolean returning such hypothetical BooleanStream.
Oracle seems to keep following this pattern, which could be found also in Collectors. There is also no such support for float primitives (there is for double primitives instead). In my opinion, unlike of float, the boolean support would make sense to implement.
Back to the code... if you have a boxed boolean array (ie. Boolean[] array), the things get easier:
Boolean[] array = ...
Stream<Boolean> streamOfBoxedBoolean1 = Arrays.stream(array);
Stream<Boolean> streamOfBoxedBoolean2 = Stream.of(array);
Otherwise you have to use more than one statement as said in this or this answer.
However, you asked (emphasizes mine):
way to convert given boolean[] foo array into stream in Java-8 in one statement.
... there is actually a way to achieve this through one statement using a Spliterator made from an Iterator. It is definetly not nice but :
boolean[] array = ...
Stream<Boolean> stream = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<>() {
int index = 0;
#Override public boolean hasNext() { return index < array.length; }
#Override public Boolean next() { return array[index++]; }
}, 0), false);

Sorting Map/TreeMap/LinkedHashMap by Value (custom data structures)

I am currently having some issues in trying to sort a Map<String, IncreaseDetails>, where IncreaseDetails is simply a custom data structure holding a few fields.
So far I have understood fairly clearly that using a TreeMap is heavily discouraged as a TreeMap should be sorted by the KeySet rather than the actual values.
I have therefore tried to switch to both HashMap and LinkedHashMap but simply calling
Collections.sort(map,comparator) doesn't seem to do the trick. Since Java 8 I was planning on trying to use the Stream API, but I don't really know it too well.
So far my comparator looks like this:
import java.util.Comparator;
import java.util.Map;
public class CompTool implements Comparator<Float> {
Map<String, IncreaseDetails> unsortedMap;
public CompTool(Map<String, IncreaseDetails> unsortedMap)
{
this.unsortedMap = unsortedMap;
}
public int compare(Float countryOne, Float countryTwo)
{
Float countryOneValue = unsortedMap.get(countryOne).getRealIncrease();
Float countryTwoValue = unsortedMap.get(countryTwo).getRealIncrease();
return countryTwoValue.compareTo(countryOneValue);
}
}
Any suggestion would be very much welcome, as I have found a lot of similar questions or videos but none too useful for my current situation.
Your question is somewhat unclear. I assume that you want to sort the unsortedMap entries by the value stored in getRealIncrease in reversed order. This can be done by creating the stream of original map entries, sorting and collecting the result into the LinkedHashMap, which preserves insertion order:
Map<String, IncreaseDetails> sortedMap = unsortedMap.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(
(Comparator.comparing(IncreaseDetails::getRealIncrease).reversed())))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> a,
LinkedHashMap::new));

error CS1729: The type `UnityEngine.Random' does not contain a constructor that takes `1' arguments

I've done some elementary coding in the past, and I'm now learning Unity and trying some things with C#.
My problem:
I have a list of objects that have their own id number in the range of 1-50. I want my game to pick one object at random instead of going over the list in order. The first step would be to pick the initial id to be some random number, but I only get the error: "error CS1729: The type UnityEngine.Random' does not contain a constructor that takes1' arguments". I understand that I should give more argument for the constructor, but I need help in seeing how, since the code looks fine (if simple) to me.
Anyway, it goes like this at the moment:
public int id;
public int randomid;
public void RandId(int id)
{
Random randomid = new Random(Random.Range(1, 51));
id = randomid;
return id;
}
Here id is the identification number of the objects, randomid is for randomizing it, and I use Random.Range to create the wanted range (1-50). It seems I need to give more arguments to Random.Range, but it already has both min and max.
Can you give me some advice?
There are some other things wrong w/ your code, but this should be what you need.
public void SetIDToRandom(out int id)
{
id = (int)Random.Range(1, 51);
}
Addendum:
Random is a static class, you don't directly instantiate it.

Two arrays or one in Map structure?

I'm trying to create a Map where the data will be static and not change after the program starts (actually loaded from a server)
Is it better to have two arrays, e.g. in Java:
String keys[] = new String[10];
String values[] = new String[10];
where keys[i] corresponds to values[i]?
or to keep them in a single array, e.g.
String[][] map[] = new String[10][2];
where map[i][0] is the key and map[i][1] is the value?
Personally, the first makes more sense to me, but the second makes more sense to my partner. Is either better performance-wise? Easier to understand?
Update: I'm looking to do this in JavaScript where Map and KeyValuePairs don't exist
Using a Map implementation (in Java) would make this easier to understand as the association is clearer:
static final Map<String, String> my_map;
static
{
my_map = new HashMap<String, String>();
// Populate.
}
A Hashtable looks like what you need. It hashes the keys in such a way that lookup can happen in O(1).
So, you're looking to do this in javascript. Any array or object in js in a map, so you could just do
var mymap = {'key1':'value1','key2':'value2'};

Resources