Related
I have two arrays with different length, but same elements. For example
A1 = {1,2,3,null,null}
A2 = {1,2,3}
Arrays.equals gives me false, because arrays have different length. Are there any method in java that will compare only elements in method?
I don't want to use .toString
I'm trying to make compare method in my own generic stack realization.
No, because its a weird request. null does not mean 'not here', null means 'unknown / unset', that's why it throws exceptions when you interact with it: You're asking "hey, thing that has not been set yet, are you X", and there is no way to answer such a question.
That doesn't mean your code is wrong, just, you can stop looking for existing implementations. Weird requests generally aren't catered to by the core libraries (or any other). You also may want to change your mindset on null. Programming in java is a lot less aggravating if at all times a NullPointerException is a good thing. In other words, avoid using null as having any semantic meaning. If you ever write if (x == null || x.isEmpty()) you are doing it wrong. Instead, where-ever 'x' is coming from, it should hold, or be updated to ASAP, the empty string instead. So, if reading in external data (e.g. you marshalled some JSON into an object), do a 'clean' step that replaces all null values that have semantic meaning with an object that actually represents it, and for methods that return stuff, always return an object that represents what you are returning - only return null if you WANT to convey the notion that there is no result (i.e. that's not the same as 'an empty result', i.e. if any code acts like there was a result, you want it to crash).
In other words, I doubt you are asking the right question. But in case you are, you have two broad options.
First make null-less arrays then compare those as normal
One option is to make new arrays that have nulls stripped. Something like:
#SuppressWarnings("unchecked")
<T> T[] stripNulls(T[] in) {
Class<?> componentType = in.getClass().getComponentType();
return (T[]) Arrays.stream(in)
.filter(x -> x != null)
.toArray(len -> java.lang.reflect.Array.newInstance(componentType, len));
}
// which you can then use; you don't need generics for a compare,
// it wouldn't add anything at all.
boolean compare(Object[] a, Object[] b) {
return Arrays.equals(stripNulls(a), stripNulls(b));
}
Just compare in place
If it's performance sensitive that's suboptimal. A better approach would involve a little more coding:
boolean compare(Object[] a, Object[] b) {
Object ae = null, be = null;
int ai = 0, bi = 0, al = a.length, bl = b.length;
while (true) {
/* set `ae` and `be` to the next non-null element */
while (ae == null && ai < al) ae = a[ai++];
while (be == null && bi < bl) be = b[bi++];
/* Have we hit the end? */
if (ai == al && bi == bl) return true;
/* If one is at the end, but the other isn't... */
if (ai == al || bi == bl) return false;
/* check if the 2 current elements are equal */
if (!ae.equals(be)) return false;
}
}
Not a native Java Developer, but maybe this helps you?
boolean arraysEqual = Arrays.equals(Arrays.stream(a1).filter(n => n != null).toArray(), Arrays.stream(a2).filter(n => n != null).toArray())
i am sure this must have been asked before in different ways - as isEmptyOrNull is so common yet people implement it differently. but i have below curious query in terms of best available approach which is good for memory and performance both.
1) Below does not account for all spaces like in case of empty XML tag
return inputString==null || inputString.length()==0;
2) Below one takes care but trim can eat some performance + memory
return inputString==null || inputString.trim().length()==0;
3) Combining one and two can save some performance + memory (As Chris suggested in comments)
return inputString==null || inputString.trim().length()==0 || inputString.trim().length()==0;
4) Converted to pattern matcher (invoked only when string is non zero length)
private static final Pattern p = Pattern.compile("\\s+");
return inputString==null || inputString.length()==0 || p.matcher(inputString).matches();
5) Using libraries like -
Apache Commons (StringUtils.isBlank/isEmpty)
or Spring (StringUtils.isEmpty)
or Guava (Strings.isNullOrEmpty)
or any other option?
Useful method from Apache Commons:
org.apache.commons.lang.StringUtils.isBlank(String str)
https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#isBlank(java.lang.String)
To detect if a string is null or empty, you can use the following without including any external dependencies on your project and still keeping your code simple/clean:
if(myString==null || myString.isEmpty()){
//do something
}
or if blank spaces need to be detected as well:
if(myString==null || myString.trim().isEmpty()){
//do something
}
you could easily wrap these into utility methods to be more concise since these are very common checks to make:
public final class StringUtils{
private StringUtils() { }
public static bool isNullOrEmpty(string s){
if(s==null || s.isEmpty()){
return true;
}
return false;
}
public static bool isNullOrWhiteSpace(string s){
if(s==null || s.trim().isEmpty()){
return true;
}
return false;
}
}
and then call these methods via:
if(StringUtils.isNullOrEmpty(myString)){...}
and
if(StringUtils.isNullOrWhiteSpace(myString)){...}
Just to show java 8's stance to remove null values.
String s = Optional.ofNullable(myString).orElse("");
if (s.trim().isEmpty()) {
...
}
Makes sense if you can use Optional<String>.
This one from Google Guava could check out "null and empty String" in the same time.
Strings.isNullOrEmpty("Your string.");
Add a dependency with Maven
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
with Gradle
dependencies {
compile 'com.google.guava:guava:20.0'
}
Haven't seen any fully-native solutions, so here's one:
return str == null || str.chars().allMatch(Character::isWhitespace);
Basically, use the native Character.isWhitespace() function. From there, you can achieve different levels of optimization, depending on how much it matters (I can assure you that in 99.99999% of use cases, no further optimization is necessary):
return str == null || str.length() == 0 || str.chars().allMatch(Character::isWhitespace);
Or, to be really optimal (but hecka ugly):
int len;
if (str == null || (len = str.length()) == 0) return true;
for (int i = 0; i < len; i++) {
if (!Character.isWhitespace(str.charAt(i))) return false;
}
return true;
One thing I like to do:
Optional<String> notBlank(String s) {
return s == null || s.chars().allMatch(Character::isWhitepace))
? Optional.empty()
: Optional.of(s);
}
...
notBlank(myStr).orElse("some default")
Apache Commons Lang has StringUtils.isEmpty(String str) method which returns true if argument is empty or null
springframework library Check whether the given String is empty.
f(StringUtils.isEmpty(str)) {
//.... String is blank or null
}
Optional.ofNullable(label)
.map(String::trim)
.map(string -> !label.isEmpty)
.orElse(false)
OR
TextUtils.isNotBlank(label);
the last solution will check if not null and trimm the str at the same time
In most of the cases, StringUtils.isBlank(str) from apache commons library would solve it. But if there is case, where input string being checked has null value within quotes, it fails to check such cases.
Take an example where I have an input object which was converted into string using String.valueOf(obj) API. In case obj reference is null, String.valueOf returns "null" instead of null.
When you attempt to use, StringUtils.isBlank("null"), API fails miserably, you may have to check for such use cases as well to make sure your validation is proper.
Simply and clearly:
if (str == null || str.trim().length() == 0) {
// str is empty
}
With the openJDK 11 you can use the internal validation to check if the String is null or just white spaces
import jdk.internal.joptsimple.internal.Strings;
...
String targetString;
if (Strings.isNullOrEmpty(tragetString)) {}
You can make use of Optional and Apache commons Stringutils library
Optional.ofNullable(StringUtils.noEmpty(string1)).orElse(string2);
here it will check if the string1 is not null and not empty else it will return string2
If you have to test more than one string in the same validation, you can do something like this:
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class StringHelper {
public static Boolean hasBlank(String ... strings) {
Predicate<String> isBlank = s -> s == null || s.trim().isEmpty();
return Optional
.ofNullable(strings)
.map(Stream::of)
.map(stream -> stream.anyMatch(isBlank))
.orElse(false);
}
}
So, you can use this like StringHelper.hasBlank("Hello", null, "", " ") or StringHelper.hasBlank("Hello") in a generic form.
We can make use of below
Optional.ofNullable(result).filter(res -> StringUtils.isNotEmpty(res))
.ifPresent( s-> val.set(s));
Is it possible to get multiple strings with .equals?
if(something.equals("String1 String2 String3")){
System.out.println(Something);
}
What I mean is:
if(choose.equals("DO IT")){
sysout blah blah blah
}
else if(choose.equals("DONT DO IT")){
...
}
No, but an alternative for many strings is to put the strings in a collection and do something like:
Set<String> strings = new HashSet<>();
strings.add("A");
strings.add("B");
strings.add("C");
if (strings.contains("D")) {
// ...
}
which is perhaps a little more concise. It's also null-safe wrt. the string you're looking to compare, which is often very useful.
Note further with Java 7 the switch statement works with strings, and that's useful if you wish to tie different actions to different strings.
If something is "String1 String2 String3" then it is equal.
If you mean contains, you can do
List<String> valid = Arrays.asList(string1, string2, string3);
if (valid.contains(something))
No you cannot. equals() takes only one object at a time.
As an alternative, you can try something like
if(something.equals("String1") || something.equals("String2") ||
something.equals("String3")) {
System.out.println(Something);
}
If you mean "can I test a string being equal to several strings in one operation", use regex:
if (something.matches("String1|String2|String3")) {
System.out.println(Something);
}
The pipe char | means "OR" in regex.
Note that in java (unlike many other languages) matches() must match the whole string - ie this is an "equals" comparison, not a "contains" comparison.
You can use a regex given the strings you match don't contain special regex characters, or are escaped.
Example:
Pattern p = Pattern.compile("^(String1|String2|String3)$");
if(p.matcher(something).find()) {
//do something
}
Or you can store the strings in a set/list and query the set:
Example:
HashSet<String> possible = new HashSet<String>();
possible.add("String1");
possible.add("String2");
possible.add("String3");
if(possible.contains(Something)) {
//do something
}
No, but you can use || to test multiple strings for equality:
if(something.equals("String1") || something.equals("String2") || something.equals("String3"))){
System.out.println(Something);
}
If you have gone through the javadocs it says
public boolean equals(Object obj); :
Indicates whether some other object is "equal to" this one.
It does not says that some other object is "equal to" these Objects.
Using equals() you can compare an Object with some other Object. It does not allow you to compare at once an Object with many other Objects. However if you want to compare an Object with many other Objects then you will need equals() for each comparasion
Well, if you want to check if there are any in such a string that don't match (aka all must match, albeit that doesn't really seem to make sense to me), then
String initString = "String1 String2 String3";
String[] splitStrings = initString.split(" ");
boolean match = true;
for(String string : splitStrings)
{
if(!string.equals(something))
{
match = false;
break;
}
}
if(match == true)
{
//did match all of them
}
else
{
//there was one that was not matched
}
If you want a "matches at least one" then it's just
String initString = "String1 String2 String3";
String[] splitStrings = initString.split(" ");
boolean match = false;
for(String string : splitStrings)
{
if(string.equals(something))
{
match = true;
break;
}
}
if(match == true)
{
//did match at least one of them
}
else
{
//didn't match any of them
}
But to be honest, Java 8 makes this simpler:
String something = "whatever";
String initString = "String1 String2 String3";
String[] splitStrings = initString.split(" ");
boolean matchAll = Arrays.stream(splitStrings).allMatch((x) -> x.equals(something));
boolean matchAny = Arrays.stream(splitStrings).anyMatch((x) -> x.equals(something));
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The following statement just looks very messy when you have a lot of terms:
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
Is there a cleaner way of performing the same action, I would like my code to be as readable as possible.
NOTE: x, y and z are just placeholders for any string of any length. There could be 20 string terms here of variable length in if condition each being OR'd together
What do you think looks "unclean" about it?
If you have a bunch of complicated boolean logic, you might separate the different parts of it into individual boolean variables and refer to them in the if statement.
Or you could create a function that takes your 'a' variable and returns a boolean. You'd just be hiding your logic in the method, but it would clean up your if statement.
Set<String> stuff = new HashSet<String>();
stuff.add("x");
stuff.add("y");
stuff.add("z");
if(stuff.contains(a)) {
//stuff
}
If this is a tight loop you can use a static Set.
static Set<String> stuff;
static {
stuff = new HashSet<String>();
stuff.add("x");
stuff.add("y");
stuff.add("z");
}
//Somewhere else in the cosmos
if(stuff.contains(a)) {
//stuff
}
And if you want to be extra sure nothing is getting modified while you're not looking.
Set<String> test = Collections.unmodifiableSet(new HashSet<String>() {
{
add("x");
add("y");
add("z");
}
});
If you just want to get some logic in there for a handful of hard coded conditions then one of the switch or if statement with newlines solutions might be better. But if you have a lot of conditions then it might be good to separate your configuration from logic.
Alternatively, if you are using Java 7+ you can use strings in switch/case. For example (I extracted this from an Oracle doc and modified)
switch (str) {
case "x":
case "y":
case "z":
//do action
break;
default:
throw new IllegalArgumentException("argument not matched "+str);
}
Here is the link
Use a regular expression
If (a.matches("[xyz]")){
// matches either "x", "y", or "z"
or, for longer strings,
If (a.matches("one|two|three")){
// matches either "one", "two" or "three"
But this is computationally expensive, but probably not much worse than instantiating a set etc. But it's the clearest way I can think of.
But in the end, the nicest way is probably to leave things as they are, with an adjustment to the formatting:
if (a.equals("x") ||
a.equals("y") ||
a.equals("z")
){
There is then absolutely no ambiguity in what the code is doing and so your code will be easier to maintain. If performance matters, you can even put the most likely occurrences towards the top of the list.
Reaching for semantics
On a semantic level, what you are checking for is set membership. However, you implement it on a very low level, basically inlining all the code needed to achieve the check. Apart from forcing the reader to infer the intent behind that massive condition, a prominent issue with such an approach is the large number of degrees of freedom in a general Boolean expression: to be sure the whole thing amounts to just checking set membership, one must carefully inspect each clause, minding any parentheses, misspellings of the repeated variable name, and more.
Each loose degree of freedom means exposure to not just one more bug, but to one more class of bugs.
An approach which uses an explicit set would have these advantages:
clear and explicit semantics;
tight constraint on the degrees of freedom to look after;
O(1) time complexity vs. O(n) complexity of your code.
This is the code needed to implement a set-based idiom:
static final Set<String> matches =
unmodifiableSet(new HashSet<>(asList("a","b","c")));
...
if (matches.contains(a)) // do something;
*I'm implying import static java.util.Arrays.asList and import static java.util.Collections.unmodifiableSet
Readability Is Mostly Formatting
Not readable...
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
Now easy to real...
if(a.equals("x") ||
a.equals("y") ||
a.equals("z") ||
Any number of terms...... )
//Do something
Readability is very subjective to the person reading the source code.
If I came across code that implements collections, loops or one of the many other complicated answers here. I'd shake my head in disbelieve.
Separate The Logic From The Problem
You are mixing two different things. There is the problem of making the business logic easy to read, and the problem of implementing the business logic.
if(validState(a))
// Do something
How you implement validState doesn't matter. What's important is that code with the if statement is readable as business logic. It should not be a long chain of Boolean operations that hide the intent of what is happening.
Here is an example of readable business logic.
if(!isCreditCard(a)) {
return false;
}
if(isExpired(a)) {
return false;
}
return paymentAuthorized(a);
At some level there has to be code that processes basic logic, strings, arrays, etc.. etc.. but it shouldn't be at this level.
If you find you often have to check if a string is equal to a bunch of other strings. Put that code into a string utility class. Separate it from your work and keep your code readable. By ensuring it shows what you're really trying to do.
You can use Arrays.asList().This is the simplest approach and less verbosity.
Arrays.asList("x","y","z"...).contains(a)
For performance reason if your collection is too big you could put data in a HashSet cause searching there is in constant time.
Example make your own util method
public final class Utils{
private Utils(){}//don't let instantiate
public static <T> boolean contains(T a,T ... x){
return new HashSet<>(Arrays.asList(x)).contains(a);
}
}
Then in your client code:
if(Utils.contains(a,"x","y","z","n")){
//execute some code
}
With a little bit of help, you can get the syntactic sugar of a nicer if-statement with just a tiny bit of overhead. To elaborate on Tim's recommendation and Jesko's recommendation a tad further...
public abstract class Criteria {
public boolean matchesAny( Object... objects ) {
for( int i = 0, count = objects.length; i < count; i++ ) {
Object object = objects[i];
if( matches( object ) ) {
return true;
}
}
return false;
}
public boolean matchesAll( Object... objects ) {
for( int i = 0, count = objects.length; i < count; i++ ) {
Object object = objects[i];
if( !matches( object ) ) {
return false;
}
}
return true;
}
public abstract boolean matches( Object object );
}
public class Identity extends Criteria {
public static Identity of( Object self ) {
return new Identity( self );
}
private final Object self;
public Identity( Object self ) {
this.self = self;
}
#Override
public boolean matches( Object object ) {
return self != null ? self.equals( object ) : object == null;
}
}
Your if-statement would then look like this:
if( Identity.of( a ).matchesAny( "x", "y", "z" ) ) {
...
}
This is sort of a middle ground between having a generic syntax for this sort of conditional matching and having the expression describe a specific intent. Following this pattern also lets you perform the same sort of matching using criteria other than equality, much like how Comparators are designed.
Even with the improved syntax, this conditional expression is still just a little bit too complex. Further refactoring might lead to externalizing the terms "x", "y", "z" and moving the expression into a method whose name clearly defines its intent:
private static final String [] IMPORTANT_TERMS = {
"x",
"y",
"z"
};
public boolean isImportant( String term ) {
return Identity.of( term ).matchesAny( IMPORTANT_TERMS );
}
...and your original if-statement would finally be reduced to...
if( isImportant( a ) ) {
...
}
That's much better, and now the method containing your conditional expression can more readily focus on Doing One Thing.
Independent of what you are trying to achieve, this
if(a.equals("x") || a.equals("y") || a.equals("z") || Any number of terms...... )
//Do something
is always messy and unclean. In the first place it is just too long to make sense of it quickly.
The simplest solution for me would be to express your intend instead of being explicit.
Try to do this instead:
public class SomeClass{
public void SomeMethod(){
if ( matchesSignificantChar(a) ){
//doSomething
}
}
private bool matchesSignificantChar(String s){
return (s.equals("x") || s.equals("y") || s.equals("z") || Any number of terms...... )
}
}
This simplifies the scope of your conditional statement and makes it easier to understand while moving the complexity to a much smaller and named scope, that is headed by your intend.
However, this is still not very extensible. If you try to make it cleaner, you can extract the boolean method into another class and pass it as a delegate to SomeClass'es Constructor or even to SomeMethod. Also you can look into the Strategy Pattern for even more exensiblity.
Keep in mind that as a programmer you will spend much more time reading code (not only yours) than writing it, so creating better understandable code will pay off in the long run.
I use following pattern
boolean cond = false; // Name this variable reasonably
cond = cond || a.equals("x");
cond = cond || a.equals("y");
cond = cond || a.equals("z");
// Any number of terms......
if (cond) {
// ...
}
Note: no objects created on the heap. Also you can use any conditions, not only "equals".
In ruby you can use operator ||= for this purpose like cond ||= a.equals("x").
The Set answer is good. When not comparing for membership of a collection you can also separate out some or all of the conditional statement into methods. For example
if (inBounds(x) && shouldProcess(x) ) {
}
If a is guaranteed to be of length 1, you could do:
if ("xyz".indexOf(a) != -1)
One really nice way to do something like this is to use ASCII values, assuming your actual case here is where a is a char or a single character string. Convert a to its ASCII integer equivalent, then use something like this:
If you want to check that a is either "t", "u", "v", ... , "z", then do.....
If (val >= 116 && val <= 122) {//code here}
I prefer to use regexp like few guys wrote upper.
But also you can use next code
private boolean isOneMoreEquals(Object arg, Object... conditions) {
if (conditions == null || arg == null) {
return false;
}
for (int i = 0, d = conditions.length; i < d; i++) {
if (arg.equals(conditions[i])) {
return true;
}
}
return false;
}
so your code will be next:
if (isOneMoreEquals(a, "x", "y", "z") {
//do something
}
Assuming that your "x", "y", and "z" can be of arbitrary length, you can use
if (0 <= java.util.Arrays.binarySearch(new String[] { "x", "y", "z" }, a)) {
// Do something
}
Just make sure that you list your items in lexicographic order, as required by binarySearch(). That should be compatible all the way back to Java 1.2, and it should be more efficient than the solutions that use Java Collections.
Of course, if your "x", "y", and "z" are all single characters, and a is also a character, you can use if (0 <= "xyz".indexOf(a)) { ... } or
switch (a) {
case 'x': case 'y': case 'z':
// Do something
}
If x,y,z... is Consecutiveļ¼ you can use if(a >= 'x' && a <= '...'), if not, you can use ArrayList or just Arrays.
I think that cleanest and fastest way is to put values in array.
String[] values={"value1","value2","value3"};
for (string value : values) {
if (a.equals(value){
//Some code
}
}
So I'm not going for maintainability or elegance here.. looking for a way to cut down on the total tokens in a method just for fun. The method is comprised of a long nested if-else construct and I've found that (I think) the way to do it with the fewest tokens is the ternary operator. Essentially, I translate this:
String method(param) {
if (param == null)
return error0;
else if (param.equals(foo1))
if (condition)
return bar1;
else
return error1;
else if (param.equals(foo2))
if (condition)
return bar2;
else
return error1;
...
else
return error;
}
to this:
String method(param) {
return
param == null ?
error0 :
param.equals(foo1) ?
condition ?
bar1 :
error1 :
param.equals(foo2) ?
condition ?
bar2 :
error2 :
...
error
}
However, there are a couple cases where in addition to returning a value I also want to change a field or call a method; e.g.,
else if (param.equals(foo3))
if (condition) {
field = value;
return bar3;
}
else
return error3;
What would be the cheapest way to do this token-wise? What I'm doing now is ugly but doesn't waste too many tokens (here the field is a String):
param.equals(foo3) && (field = value) instanceOf String ?
condition ?
bar2 :
error2 :
Again, the point is not good coding, I'm just looking for hacks to decrease the token count. If there's a shorter way to write the entire thing I'm open to that as well. Thanks for any suggestions.
Edit: Each word and punctuation mark counts as one token. So, for example, "instanceOf String" is two tokens, but "!= null" is three. The main things I can see for possible improvement are the "&&" and the parentheses. Is there a way to put "field = value" somewhere besides the conditional, and if not is there a construct that makes "field = value" a boolean without the need for parentheses?
(field = value) instanceof String
Assuming that it already satisfies your needs (and it thus includes returning false when value is null), a shorter alternative would then have been
(field = value) != null
Or if you actually overlooked that and want to make null return true as well, then use
(field = value) == value
This can be made much shorter if you use 1-letter variable names.
Further I don't see other ways and I agree with most of us that this all is somewhat nasty ;)
if param is null, return 0
Then make a case/switch/select statement on the parameter. That's clean .