Java check if Map values are the same [duplicate] - java

I need to check if all values in a map are equal. I have a method to perform this task but would like to use a library or native methods. Limitations: Java 5 + Apache Commons libraries.
public static boolean isUnique(Map<Dboid,?> aMap){
boolean isUnique = true;
Object currValue = null;
int iteration = 0;
Iterator<?> it = aMap.entrySet().iterator();
while(it.hasNext() && isUnique){
iteration++;
Object value = it.next();
if(iteration > 1){
if (value != null && currValue == null ||
value == null && currValue != null ||
value != null && currValue != null & !value.equals(currValue)) {
isUnique = false;
}
}
currValue = value;
}
return isUnique;
}

What about this something like this:
Set<String> values = new HashSet<String>(aMap.values());
boolean isUnique = values.size() == 1;

how about
return (new HashSet(aMap.values()).size() == 1)

I know the original questions asks for solutions in Java 5, but in case someone else searching for an answer to this question is not limited to Java 5 here is a Java 8 approach.
return aMap.values().stream().distinct().limit(2).count() < 2

You could store the values in a Bidirectional Map and always have this property.

public static boolean isUnique(Map<Dboid,?> aMap) {
Set<Object> values = new HashSet<Object>();
for (Map.Entry<Dboid,?> entry : aMap.entrySet()) {
if (!values.isEmpty() && values.add(entry.getValue())) {
return false;
}
}
return true;
}
This solution has the advantage to offer a memory-saving short cut if there are many differences in the map. For the special case of an empty Map you might choose false as return value, change it appropriately for your purpose.
Or even better without a Set (if your Map does not contain null-values):
public static boolean isUnique(Map<Dboid,?> aMap) {
Object value = null;
for (Object entry : aMap.values()) {
if (value == null) {
value = entry;
} else if (!value.equals(entry)) {
return false;
}
}
return true;
}

As my comment above:
//think in a more proper name isAllValuesAreUnique for example
public static boolean isUnique(Map<Dboid,?> aMap){
if(aMap == null)
return true; // or throw IlegalArgumentException()
Collection<?> c = aMap.getValues();
return new HashSet<>(c).size() <= 1;
}

Related

Sorting null values in displaytag library

I have a <display:table> with potential null values in the columns, and I'd like to configure the sorting so that when a given <display:column> is sorted alphabetically ("A" strings at top), the null values are at the bottom of the table (after "Z" strings).
To do this, I've written a Comparator implementation that should put null values at the end of the list:
public class DefaultComparatorNullsLast implements Comparator<Object>{
private final Collator collator;
public DefaultComparatorNullsLast(){
this(Collator.getInstance());
} // DefaultComparatorNullsLast
public DefaultComparatorNullsLast(Collator collatorToUse){
this.collator = collatorToUse;
this.collator.setStrength(Collator.PRIMARY);
} // DefaultComparatorNullsLast
public int compare(final Object obj0, final Object obj1){
//similar to NullComparator.compare()
if(obj0 == obj1) return 0;
else if(obj0 == null) return 1;
else if(obj1 == null) return -1;
//similar to DefaultComparator.compare()
if(obj0 instanceof String && obj1 instanceof String) return this.collator.compare(obj0, obj1);
else if(obj0 instanceof Comparable && obj1 instanceof Comparable) return ((Comparable<Object>) obj0).compareTo(obj1);
else return this.collator.compare(obj0.toString(), obj1.toString());
} // compare
} // DefaultComparatorNullsLast
Strangely, though, the null values are still displaying at the top of the table. When I debug, I see that my DefaultComparatorNullsLast.compare() method is never called on any null values. Digging into the displaytag code, I can see that TableModel.sortRowList() actually places my Comparator implementation into a RowSorter, which is then passed to Collections.sort():
private void sortRowList(List list)
{
if (isSorted())
{
HeaderCell sortedHeaderCell = getSortedColumnHeader();
if (sortedHeaderCell != null)
{
// If it is an explicit value, then sort by that, otherwise sort by the property...
if (sortedHeaderCell.getBeanPropertyName() != null
|| (this.sortedColumn != -1 && this.sortedColumn < this.headerCellList.size()))
{
String sorted = (sortedHeaderCell.getSortProperty() != null)
? sortedHeaderCell.getSortProperty()
: sortedHeaderCell.getBeanPropertyName();
Collections.sort(list, new RowSorter(
this.sortedColumn,
sorted,
getTableDecorator(),
this.sortOrderAscending,
sortedHeaderCell.getComparator()));
}
}
}
}
And when I look into RowSorter, it seems the checkNullsAndCompare() method actually handles null values opposite how I want them to be handled and only calls my DefaultComparatorNullsLast.compare() method if both values are non-null:
private int checkNullsAndCompare(Object object1, Object object2)
{
int returnValue;
if (object1 == null && object2 != null)
{
returnValue = -1;
}
else if (object1 != null && object2 == null)
{
returnValue = 1;
}
else if (object1 == null && object2 == null)
{
// both null
returnValue = 0;
}
else
{
returnValue = comparator.compare(object1, object2);
}
int ascendingInt = this.ascending ? 1 : -1;
return ascendingInt * returnValue;
}
Essentially, I'm wondering if there's any way around this. Of course, I know I can sort the list in my action code before the JSP renders and use sort="external", but I also want this special sorting of null values to take place when the user clicks a column header to sort by that column's property. Is there any way to get the displaytag library to call my custom Comparator implementation instead of RowSorter.checkNullsAndCompare()?

Combining two similar methods in Java with predicate

I have two similar methods in terms of the body, but with a different number of parameters and an extra condition inside. I know there is a way of merging them into a single method using a predicate, but I am not entirely sure how to implement it. Which is the best way to approach this?
public boolean checkIfAllCodesAreUnique(List<String> bsnCodes)
{
List<Businesscode> codes = ConverterUtil.iterableToList(businessCodeService.findAll());
if(codes != null && !codes.isEmpty() && bsnCodes != null && !bsnCodes.isEmpty())
for (String code : bsnCodes)
if (codes.stream().anyMatch(obj -> code.equals(obj.getCode())))
return false;
return true;
}
public boolean checkIfAllCodesAreUnique(List<String> bsnCodes, int idRole)
{
List<Businesscode> codes = ConverterUtil.iterableToList(businessCodeService.findAll());
if(codes != null && !codes.isEmpty() && bsnCodes != null && !bsnCodes.isEmpty())
for (String code : bsnCodes)
if (codes.stream().anyMatch(obj -> code.equals(obj.getCode()) && obj.getId() != idRole))
return false;
return true;
}
public boolean checkIfAllCodesAreUnique(List<String> bsnCodes) {
return isAllCodesAreUnique(bsnCodes, businessCode -> true);
}
public boolean checkIfAllCodesAreUnique(List<String> bsnCodes, int idRole) {
return isAllCodesAreUnique(bsnCodes, businessCode -> businessCode.getId() != idRole);
}
private boolean isAllCodesAreUnique(List<String> bsnCodes, Predicate<Businesscode> checkRole) {
List<Businesscode> businessCodes = Optional.ofNullable(ConverterUtil
.iterableToList(businessCodeService.findAll())).orElse(List.of());
for (String bsnCode : Optional.ofNullable(bsnCodes).orElse(List.of())) {
if (businessCodes.stream()
.filter(businessCode -> bsnCode.equals(businessCode.getCode()))
.anyMatch(checkRole))
return false;
}
return true;
}
Basically predicate would not allow you anything specific in the sense of auto-determinable interface or whatever. Probably the best combination of the two would be:
public boolean checkIfAllCodesAreUnique(List<String> bsnCodes, Integer idRole)
{
List<Businesscode> codes = ConverterUtil.iterableToList(businessCodeService.findAll());
if(codes != null && !codes.isEmpty() && bsnCodes != null && !bsnCodes.isEmpty())
for (String code : bsnCodes)
if (codes.stream().anyMatch(obj -> code.equals(obj.getCode()) || (idRole != null && obj.getId() != idRole))
return false;
return true;
}
And then pass the second parameter as null whenever not available.

How to handle null values when doing Collections.sort() with nested objects?

What is the best way to deal with null values, when doing Collections.sort() on nested objects?
I'd like to sort a couple of objects, basically applying this rule:
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
However, any of these objects can be null (i.e. invoice position, invoice and invoice number).
public class InvoicePos {
private Invoice invoice = null;
// ...
}
public class Invoice {
private String invoiceNo = "";
// ...
}
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
For clarification: I'm aware that my above example may raise NullPointerExceptions. Currently I'm doing the following and basically, I questioned myself, if there is any smarter approach.
Collections.sort(allInvoicePositions, new Comparator<InvoicePos>() {
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
if (null == invoicePosOne && null == invoicePosTwo) {
return 0;
}
if (null == invoicePosOne) {
return -1;
}
if (null == invoicePosTwo) {
return 1;
}
if (null == invoicePosOne.getInvoice() && null == invoicePosTwo.getInvoice()) {
return 0;
}
if (null == invoicePosOne.getInvoice()) {
return -1;
}
if (null == invoicePosTwo.getInvoice()) {
return 1;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo() && null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 0;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo()) {
return -1;
}
if (null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 1;
}
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
});
There is something called as NullComparator in org.apache.commons.collections.jar.
This might help you https://commons.apache.org/proper/commons-collections/javadocs/api-2.1.1/org/apache/commons/collections/comparators/NullComparator.html.
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
If these values don't represent anything in your collection, then the best thing you can do is avoid them; don't allow inserting them, so you won't have to handle them when comparing items.
If you insist to have them, then you must check if they're null to avoid NullPointerException.
If you have null values then you need to handle them explicitly and in a consistent way so to have a valid ordering relation. That is, something like:
compare (a, b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return +1;
return comp(a,b);
}
Don't be tempted to do something like:
compare (a, b) {
if (a == null || b == null) return -1;
return comp(a,b);
}
which would break the ordering relation.

Java HashMap Iterate Each Variable and Return Value

I have a class with various Booleans and Integers.
class Animal {
boolean mHappy = false;
boolean mHungry = false;
boolean mSleeping = false;
int mCost = 0;
int mWeight = 0;
boolean isEmpty() {
return !mHappy && !mHungry && !mSleeping && mCost == 0 && mWeight == 0;
}
}
The method boolean isEmpty() will tell me if all the values are empty.
Now, I want to move all my data into HashMaps:
class Animal {
HashMap<String, Boolean> mBools = new HashMap<String, Boolean>(){{
put("mHappy", false);
put("mHungry", false);
put("mSleeping", false);
}
};
HashMap<String, Integer> mInts = new HashMap<String, Integer>(){{
put("mCost", 0);
put("mWeight", 0);
}
};
boolean isEmpty() {
// MY QUESTION: How can I make this function iterate through each HashMap,
// regardless of size, and check to make sure it's "false" or "0" like this
// line did when I only was using static booleans and integers?
return !mHappy && !mHungry && !mSleeping && mCost == 0 && mWeight == 0;
}
}
My Question is about the "boolean isEmpty()" method, How can I make this function iterate through each HashMap, regardless of size, and check to make sure each value is "false" or "0"?
This will do it:
boolean isEmpty() {
for (int i : mInts.values()) if (i != 0) return false;
for (boolean b : mBools.values()) if (b) return false;
return true;
}
Read the map tutorial for more info about iterating through the contents of a map.
Call the values() method on each map; you can iterate through the returned Collection of values. Then you can check each value to see if they are 0 or false as the case may be.
Keep a boolean, initialized to true, if everything is "empty" so far. Set it to false if a value isn't 0 or false.
You just need to iterate over the values in your maps:
boolean isEmpty {
for (Integer i : mInts.values()) {
if (i > 0) {
return false;
}
}
for (Boolean b : mBools.values()) {
if (b) {
return false;
}
}
return true;
}

Remove Repeated Code

My Question is-
I have two string variables site_inclusion and site_exclusion. If site_inclusion has a value, then I don't care what values site_exclusion contains. That is to say that site_inclusion overrides site_exclusion. If, however, site_inclusion is null and site_exclusion has a value, then I want to examine site_exclusion.
To be more precise:
If site_inclusion and site_exclusion are both null then set useTheSynthesizer as true;
If site_inclusion is not null and it matches with the regexPattern then set useTheSynthesizer as true. And I don't care what values are there in site_exclusion.
If site_inclusion is null and site_exclusion is not null and site_exclusion does not match the regexPattern then set useTheSynthesizer to true.
I wrote the below code but somehow I think, I am repeating some stuff here in the if/else loop. Any code improvements will be appreciated that fulfill my conditions.
String site_inclusion = metadata.getSiteInclusion();
String site_exclusion = metadata.getSiteExclusion();
// fix for redundant data per site issue
if(site_inclusion != null && site_inclusion.matches(regexPattern)) {
useTheSynthesizer = true;
} else if(site_exclusion != null && !(site_exclusion.matches(regexPattern))) {
useTheSynthesizer = true;
} else if(site_inclusion == null && site_exclusion == null ) {
useTheSynthesizer = true;
}
You don't really need the last null test.
I (personally) find it poor style to do an if(test == true) flag = true statement. You can simply say flag = test.
My recommendation would be:
if(site_inclusion != null)
{
useTheSynthesizer = site_inclusion.matches(regexPattern);
}
else if(site_exclusion != null)
{
useTheSynthesizer = ! site_exclusion.matches(regexPattern);
}
else
{
useTheSynthesizer = true;
}
You could also do it in a oneliner:
useTheSynthesizer = site_inclusion != null ? site_inclusion.matches(regexPattern) : (site_exclusion != null ? ! site_exclusion.matches(regexPattern) : true);
But I find that sort of obnoxious to read.
(Note, I made the assumption that useTheSynthesizer was otherwise false. This isn't explicit in your code or explanation, but I think this assumption was safe.)
I would do it like this:
boolean useTheSynthesizer;
if (siteInclusion == null && siteExclusion == null) {
useTheSynthesizer = true;
}
else if (siteInclusion == null) {
useTheSynthesizer = ( ! siteExclusion.matches(regexPattern) );
}
else {
useTheSynthesizer = siteInclusion.matches(regexPattern);
}
I also removed the underscores from your variable names, since they do not fit the java naming conventions (and they're hideous IMO).
You can do like this. Basically i extracted all the conditions as small methods and made as OR condition.
String site_inclusion = metadata.getSiteInclusion();
String site_exclusion = metadata.getSiteExclusion();
if(isInclusionAndExclusionNull(site_inclusion, site_exclusion) || isSiteExclusionMatches(site_exclusion, regexPattern) || isSiteInclusionMatches(site_inclusion, regexPattern)) {
useTheSynthesizer = true;
}
private static boolean isInclusionAndExclusionNull(String site_inclusion,
String site_exclusion) {
return site_inclusion == null && site_exclusion == null;
}
private boolean isSiteExclusionMatches(String site_exclusion,
String regexPattern) {
return site_exclusion != null && !(site_exclusion.matches(regexPattern));
}
private boolean isSiteInclusionMatches(String site_inclusion,
String regexPattern) {
return site_inclusion != null && site_inclusion.matches(regexPattern);
}
You can have 2 methods for flexibility to process the inclusions and exclusions like below..
callingMethod() {
boolean useTheSynthesizer = processSiteInclusions(site_inclusion, regexPattern);
if (useTheSynthesizer == false) {
useTheSynthesizer = processSiteExclusions(site_inclusion, regexPattern);
}
if (useTheSynthesizer == false) {
useTheSynthesizer = true;
}
}
private boolean processSiteInclusions(site_inclusion, regexPattern) {
boolean useSynthesizer = false;
if (site_inclusion != null && !site_inclusion.matches(regexPattern))
useSynthesizer = true;
return useSynthesizer;
}
private boolean processSiteExclusions(site_exclusion, regexPattern) {
boolean useSynthesizer = false;
if (site_exclusion != null && !site_inclusion.matches(regexPattern))
useSynthesizer = true;
return useSynthesizer;
}
Hello I think you can improve it using some like OR, and no only AND or try somethin like swicht case.
Anyways you can create some function that tested your variables, and you can write this confusing code out from your main module.
For example you can write this code in a function called boolean TestingVariable ( String X, String Y);
For example:
boolean TesteingVariable ( String X, String Y){
if(X != null && X.matches(regexPattern)) {
return true;
} else if(Y != null && !(Y.matches(regexPattern))) {
return = true;
} else if(X == null && Y == null ) {
return = true;
}
};
On this way your final main module code will be something like this and you will avoid the confused code in your main code:
String site_inclusion = metadata.getSiteInclusion();
String site_exclusion = metadata.getSiteExclusion();
// fix for redundant data per site issue
useTheSynthesizer = TesteingVariable (site_inclusion ,site_exclusion);
I think you should enter the variable regexPattern in the function.
Sorry for my English I hope you can undertand all and it help to you.

Categories