I want to find element present in list and it compare with Enum value - spring

I have a List it has multiple object is present. for every object we have to find some string which compare to Enum value How we get list of particular object
public enum ObjectType {
CONTACT("Contact"),
BANK_DETAILS("Bank-Details"),
EMPLOYMENT("Employment"),
PRODUCT("Product"),
INCOME_DETAIL("Income-Details");
ObjectType(String values) { this.values = values; }
public String getValues() { return values; }
private String values; }
for this i am using below method
List listOutput = errorsList.stream().
filter(e -> e.getObjType().contains(String.valueOf(ObjectType.values())))
.collect(Collectors.toList());
But it return 0 value are present

Try this (adding check method to enum):
public enum ObjectType {
CONTACT("Contact"),
BANK_DETAILS("Bank-Details"),
EMPLOYMENT("Employment"),
PRODUCT("Product"),
INCOME_DETAIL("Income-Details");
private String values;
ObjectType(String values) {
this.values = values;
}
public String getValues() {
return values;
}
public static boolean isValueExists(String test) {
for (ObjectType o : ObjectType.values()) {
if (o.getValues().equals(test)) {
return true;
}
}
return false;
}
}
And then use it:
List listOutput = errorsList.stream().filter(e -> ObjectType.isValueExists(e.getObjType())).collect(Collectors.toList());

Related

Java8 Streams: Remove an field from an object of the map value

I have a hash map like this
Map<String, AttributeValueUpdate> myMap = new HashMap<>;
The class AttributeValueUpdate looks like this:
public class AttributeValueUpdate {
private AttributeValue value;
private String action;
public static class Builder {
private AttributeValue value;
private String action;
public Builder() {
}
public AttributeValueUpdate.Builder withValue(AttributeValue value) {
this.value = value;
return this;
}
public AttributeValueUpdate.Builder withAction(String action) {
this.action = action;
return this;
}
protected void populate(AttributeValueUpdate instance) {
instance.setValue(this.value);
instance.setAction(this.action);
}
public AttributeValueUpdate build() {
AttributeValueUpdate instance = new AttributeValueUpdate();
this.populate(instance);
return instance;
}
}
}
The map has two entries
AttributeValueUpdate att1 = AttributeValueUpdate.builder().withAction("Add").withValue(new AttributeValue("sam").build();
AttributeValueUpdate att2 = AttributeValueUpdate.builder().withAction("Delete").withValue(new AttributeValue("john").build();
myMap.add("entry1", attr1);
myMap.add("entry2", atte2);
I want to modify mymap by deleting the "value field" from all the AttributeValueUpdate (which is value of the map), basically map's value field will be changed by removing "value field" of the AttributeValueUpdate object. How can I achieve this using java streams?
Java Stream API is not a friend with Map as long as it's collection-based (List, Set). You need to stream over the entries of the map.
As far as I understand, you want to remove (= make null) AttributeValue value of each AttributeValueUpdate instance (map's value). Here is the way to go assuming a constructor AttributeValueUpdate(String action):
Map<String, AttributeValueUpdate> updatedMap = myMap.entrySet().stream()
.map(entry -> {
String action = entry.getValue().getAction();
AttributeValueUpdate update = new AttributeValueUpdate(action);
return new SimpleEntry<>(entry.getKey(), update);
})
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
The easiest solution is using Map#replaceAll if you don't mind to mutate the map:
myMap.replaceAll((k, v) -> {
String action = v.getAction();
return new AttributeValueUpdate(action);
});

Collecting data from map to list using Java 8

Please help me with the Java 8 map - filter - sort - collect code.
Info.java
public class Info {
private final String name;
private final String desc;
private String version = null;
#Override
public boolean equals(Object that) {
if (that == null) {
return false;
}
if (that instanceof Info) {
Info other = (Info) that;
return Objects.equals(this.name, other.name) &&
Objects.equals(this.desc, other.desc) &&
Objects.equals(this.version, other.version);
} else {
return false;
}
}
public boolean equalsWithoutVersion(Object that) {
if (that == null) {
return false;
}
if (that instanceof Info) {
Info other = (Info) that;
return Objects.equals(this.name, other.name) &&
Objects.equals(this.desc, other.desc);
} else {
return false;
}
}
#Override
public int hashCode() {
int hash = 13;
hash = (hash * 7) + name.hashCode();
hash = (hash * 7) + desc.hashCode();
if (version != null)
hash = (hash * 7) + version.hashCode();
return hash;
}
#Override
public String toString() {
String versionString = version == null ? "latest" : version;
return String.format("Name: %s Desc: %s Key Type: %s Version: %s", this.name, this.desc, this.keyType.name(), versionString);
}
}
Value.java
public class Value implements Comparable<Value> {
private String data;
private String version;
public Value(String version, String data) {
this.version = version;
this.data = data;
}
#Override
public int compareTo(Value o) {
return (Integer.parseInt(this.version) > Integer.parseInt(o.version)) ? -1
: (Integer.parseInt(this.version) < Integer.parseInt(o.version)) ? 1
: 0;
}
}
Cache.java
public class Cache {
private final Map<Info, Value> dataMap = new HashMap<>();
...
private Value getlatestVersionFromCache(Info info) {
List<Value> values = dataMap.entrySet().stream()
.filter(p -> p.getKey().equalsWithoutVersion(info))
.sorted(Map.Entry.comparingByValue())
.map(x::getValue))
.collect(Collectors.toList());
return values.isEmpty() ? null : values.get(0);
}
}
The goal is to obtain the latest version of a record from the map. So first I am filtering entries from the map by comparing fields of Info without version. Then I am sorting the map by value based on version. Then I am collecting the values to a list. Then I can get the first element to get the latest version.
But I am getting the following compilation error on the filter statement:
Syntax error on token ")", ElidedSemicolonAndRightBrace expected
Well I doubt about your solution. I think you can do it in simple way. so first change version type to Integer in Value class(in compareTo() method you converted it to Integer). and also change method signature to Optional<Value> in getlatestVersionFromCache() method.
also I think you don't need to sort dataMap.
private Optional<Value> getlatestVersionFromCache(Info info) {
Map<Value,Integer> result = dataMap.entrySet()
.stream()
.filter(p -> p.getKey().equalsWithoutVersion(info))
.collect(Collectors.toMap(Map.Entry::getValue, entry -> entry.getValue().getVersion(), Integer::min));
Optional<Value> latestValue = result.keySet()
.stream()
.min(Comparator.comparingInt(key -> key.getVersion()));
return latestValue;
}
Better solution is something like this:
dataMap.entrySet()
.stream()
.filter(p -> p.getKey().equalsWithoutVersion(info))
.min(Comparator.comparingInt(entry -> entry.getValue().getVersion()))
.map(Map.Entry::getValue)
.orElse(null);
You have several omissions and errors in the code you posted, but the filter statement was actually fine.
The following passes compilation:
List<Value> values = dataMap.entrySet()
.stream()
.filter(p -> p.getKey().equalsWithoutVersion(info))
.sorted(Map.Entry.comparingByValue())
.map(Map.Entry::getValue) // was .map(x::getValue)) - x is not defined anywhere, so
// I assumed you meant Map.Entry::getValue
.collect(Collectors.toList());
class Info {
public static final BiPredicate<Info, Info> IS_EQUAL_IGNORE_VERSION =
(one, two) -> one.getName().equals(two.getName()) && one.getDesc().equals(two.getDesc());
private final String name;
private final String desc;
private String version;
}
private final Map<Info, Value> dataMap = new HashMap<>();
public Value getlatestVersionFromCache(Info info) {
Value value = null;
for (Map.Entry<Info, Value> entry : dataMap.entrySet())
if (Info.IS_EQUAL_IGNORE_VERSION.test(entry.getKey(), info))
if (value == null || Integer.parseInt(entry.getValue().getVersion()) > Integer.parseInt(value.getVersion()))
value = entry.getValue();
return value;
}
Notes:
I think that use a comparator to check that two objects are queal is not correct. You can use e.g. Predicate. And define it as a static method in the target class.
Pay attention on version. It seems that it should be an integer instead of String.
In your approach, compare two string is not correct, because it is used instead of equals method.
I think that using Java8 streams only because this is a stream is alow not correct.

Dynamic Filtering of ArrayList with another ArrayList Java 8

I have a few Search Results Objects as given below:
public class TradeSearchResult{
private String tradeRefNo;
private String relatedTradeId;
private String custodyDate;
private String orderNumber;
private String odrQty;
private String price : 500;
}
public class CollateralTradesSearchResult{
private String excludeTradeOUT;
private String settlementStatus;
private String fundId;
private String altFundId;
private String apNumber;
private String collateralOrderNumber;
private String componenetIdentifier;
}
Now I have a Search Filter Criteria object
public class CRITERION {
protected String field; //The field denotes any field name of the either
SearchResult object
protected String operator; its will be EQUALS or NOT_EQUALS
protected String value; Value of the field.
}
Now I need to write a Dynamic Filter Method where I will pass the List of Criterion object and can pass List of either SearchResult like below
public static List<Object> applyFilter(List<CRITERION> comp, List<?> objectList){
//The CRITERION.fiedName can be same in more than one in the list
return filteredList;
}
here is one example: Consider the below List of
TradeSearchResult{
tradeRefNo : W12343;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342343;
String odrQty : 12;
String price : 500;
},
{
tradeRefNo : W12344;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342344;
String odrQty : 18;
String price : 600;
},
{
tradeRefNo : W12345;
relatedTradeId: N993094;
custodyDate : 2018-12-14;
orderNumber : 0000342345;
String odrQty : 20;
String price : 700;
}
Now the Criterion class is like
CRITERION{
field :relatedTradeId;
operator : EQUALS;
value :N993093;
}
{
field :relatedTradeId;
operator : EQUALS;
value :N993094;
}
{
field :orderNumber ;
operator : EQUALS;
value :0000342344;
}
It will only return one result even relatedTradeId has two filter
TradeSearchResult{
tradeRefNo : W12344;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342344;
String odrQty : 18;
String price : 600;
}
Now in the same applyFIlter Method I can send a list of Criterion and a list of CollateralTradesSearchResult and returns filtered result.
Here is something I tried
public static List<Object> applyFilter(List<CRITERION> criList, List<?> objectList){
long startTime = Calendar.getInstance().getTimeInMillis();
Set<Object> objectSet = new HashSet<>();
for(CRITERION cri : criList){
String fieldName = cri.getFIELD();
objectList.stream().filter(p->beanProperties(p).get(fieldName).equals(cri.getVALUE())).forEachOrdered(objectSet::add);
//objectList.retainAll(objectSet);
//objectSet.clear();
}
List<Object> ret = new ArrayList<>(objectSet);
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Size"+ ret.size());
System.out.println("Time Taken to Search"+ String.valueOf(endTime-startTime));
return ret;
}
Hereis the beanProperties() method
public static Map<String, Object> beanProperties(Object bean) {
try {
Map<String, Object> map = new HashMap<>();
Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.forEach(pd -> { // invoke method to get value
try {
Object value = pd.getReadMethod().invoke(bean);
if (value != null) {
map.put(pd.getName(), value);
}
} catch (Exception e) {
// add proper error handling here
}
});
return map;
} catch (IntrospectionException e) {
// and here, too
return Collections.emptyMap();
}
}
Any help using Stream or by any means will be helpful.
Create an interface SearchResult and make both your classes implement it. Then create this class:
public class Filter<T extends SearchResult> {
public List<T> applyFilter(List<Criterion> criteria, List<T> list) {
Map<String, Set<String>> allowedValues = new HashMap<>();
Map<String, Set<String>> prohibitedValues = new HashMap<>();
populateValues(criteria, "EQUALS", allowedValues);
populateValues(criteria, "NOT_EQUALS", prohibitedValues);
prohibitedValues.forEach((k, v) -> list.removeIf(t -> v.contains(getFieldValue(k, t))));
allowedValues.forEach((k, v) -> list.removeIf(t -> !v.contains(getFieldValue(k, t))));
return list;
}
private static void populateValues(List<Criterion> criteria, String operator, Map<String, Set<String>> values) {
criteria.stream()
.filter(c -> c.getOperator().equals(operator))
.forEach(c -> {
values.merge(c.getField(), Stream.of(c.getValue()).collect(Collectors.toSet()),
(set1, set2) -> Stream.concat(set1.stream(), set2.stream()).collect(Collectors.toSet()));
});
}
private String getFieldValue(String fieldName, T object) {
Field field;
try {
field = object.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
e.printStackTrace();
return null;
}
field.setAccessible(true);
try {
return (String) field.get(object);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
And use it as:
Filter<TradeSearchResult> filter = new Filter<>(); //or CollateralTradesSearchResult
List<TradeSearchResult> filteredList = filter.applyFilter(criteria, searchResults);

Equal Collection returns false when Object implements IEquatable?

I have the following test example:
var a = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var b = new List<OrderRule> {
new OrderRule("name", OrderDirection.Ascending),
new OrderRule("age", OrderDirection.Descending)
};
var r = a.SequenceEqual(b);
Assert.Equal(a, b);
The variable r is true but Assert.Equal is false ...
The OrderRule class is the following:
public class OrderRule : IEquatable<OrderRule> {
public OrderDirection Direction { get; }
public String Property { get; }
public OrderRule(String property, OrderDirection direction) {
Direction = direction;
Property = property;
}
public Boolean Equals(OrderRule other) {
if (other == null)
return false;
return Property.Equals(other.Property) && Direction.Equals(other.Direction);
}
public override Boolean Equals(Object obj) {
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals(obj as IncludeRule);
}
public override Int32 GetHashCode() {
return HashCode.Of(Property).And(Direction);
}
}
public enum OrderDirection { ASC, DESC }
Is there any problem with Assert.Equal when overriding Equals and implementing IEquatable?
UPDATE - HashCode helper
public struct HashCode {
private readonly Int32 Value;
private HashCode(Int32 value) {
Value = value;
}
public static implicit operator Int32(HashCode hashCode) {
return hashCode.Value;
}
public static HashCode Of<T>(T item) {
return new HashCode(GetHashCode(item));
}
public HashCode And<T>(T item) {
return new HashCode(CombineHashCodes(Value, GetHashCode(item)));
}
public HashCode AndEach<T>(IEnumerable<T> items) {
Int32 hashCode = items.Select(x => GetHashCode(x)).Aggregate((x, y) => CombineHashCodes(x, y));
return new HashCode(CombineHashCodes(Value, hashCode));
}
private static Int32 CombineHashCodes(Int32 x, Int32 y) {
unchecked {
return ((x << 5) + x) ^ y;
}
}
private static Int32 GetHashCode<T>(T item) {
return item == null ? 0 : item.GetHashCode();
}
}
Your code works as expected on my side. I've only fixed compilation erros - IncludeRule changed to OrderRule in Equals, also fixed OrderDirection enum members.

Required Validation based on condition

public string InsuredName
{
get;
set;
}
public string Card_No
{
get { return this.card_No; }
set { this.card_No = value; }
}
here i have two properites, CardNo will be required only for some InsuredNames.when User types InsuredName then i want to go to database and check wheather it has Card_No validation if yes then i want to validate it as required other wise not, i tried remote validation but it is not working
private string insuredName;
private bool cardNoRequiresValidation;
public string InsuredName
{
get {return insuredName;}
set { cardNoRequiresValidation = DoesCardNoRequiresValidation(Value); insuredName = value;}
}
public string Card_No
{
get { return this.card_No; }
set { cardNoRequiresValidation ? ValidateCardNo(value) : card_No = value; }
}
private bool DoesCardNoRequiresValidation(string insuredName)
{ //if requires validation
// return true;
//else
//return false;
}
private void ValidateCardNo(string cardNo)
{
//execute validation logic
}

Resources