Stream different data types - java

I'm getting my head around Streams API.
What is happening with the 2 in the first line? What data type is it treated as? Why doesn't this print true?
System.out.println(Stream.of("hi", "there",2).anyMatch(i->i=="2"));
The second part of this question is why doesn't the below code compile (2 is not in quotes)?
System.out.println(Stream.of("hi", "there",2).anyMatch(i->i==2));

In the first snippet, you are creating a Stream of Objects. The 2 element is an Integer, so comparing it to the String "2" returns false.
In the second snippet, you can't compare an arbitrary Object to the int 2, since there is no conversion from Object to 2.
For the first snippet to return true, you have to change the last element of the Stream to a String (and also use equals instead of == in order not to rely on the String pool):
System.out.println(Stream.of("hi", "there", "2").anyMatch(i->i.equals("2")));
The second snippet can be fixed by using equals instead of ==, since equals exists for any Object:
System.out.println(Stream.of("hi", "there",2).anyMatch(i->i.equals(2)));

You should instead make use of:
System.out.println(Stream.of("hi", "there",2).anyMatch(i->i.equals(2)));
The reason for that is the comparison within the anyMatch you're doing is for i which is an Object(from the stream) and is incompatible with an int.
Also, note that the first part compiles successfully since you are comparing an integer(object) with an object string "2" in there and hence returns false.

Related

Java very long string compare seems not to work

Update:
Using your suggestions in checking between strings, I found out that the difference is on the arrangement of some fields since these strings are actually JSON strings.
Example:
the field username: johndoe#dummy.com on string1 is located at the beginning, but is located somewhere in the middle in string2.
I wonder if there is a way to check or compare 2 json objects regardless of the arrangement of their fields/properties... as long as their contents (field values) are the same.
What I tried:
private boolean sameJsonObject(Object o1, Object o2) throws IOException {
if (o1 == null || o2 == null) {
return false;
}
JsonNode json1 = mapper.readTree(mapper.writeValueAsString(o1));
JsonNode json2 = mapper.readTree(mapper.writeValueAsString(o2));
return json1.equals(json2);
}
this works but I am sure that this can be improved.
Original Problem:
I would like to check if two strings are equal, but these strings are really long that it cannot be set to a variable/string object and would get string constant too long.
I know that there is equals(), equalsIgnoreCase(), and StringUtils.equals(s1, s2) but none of these seems to work.
The strings that I am comparing came from two different sources and comparing it manually get the same results (I mean the contents are the same).
I tried to post the sample strings here but I can't. The size of each string to compare is more than 30k (170k each string).
btw, these strings are actual data (json) and they are really huge and I want to test its equality (content).
Is there a way to do the checking in java?
Thanks!
The simple answer is: compare the two strings char by char.
In other words: most likely, the built-in Java string compare methods are correct, leading to: your input strings aren't equal. It is extremely unlikely that equal strings result in equals() giving false.
Thus the reasonable first option is: change your comparison code so that it:
iterates the first string, char by char
fetches the corresponding char from the second string
compares those (either "full" equals, or ignoring case)
on mismatch: print out the index and the two different chars (where you ensure to print something like "<" + thatChar + ">" just to ensure that non-printable chars, or maybe using Character.getNumericValue())
So, the answer here is basically to enable yourself to do proper debugging.
btw, these strings are actual data (json) and they are really huge and
I want to test its equality (content).
If these are JSON data, don't compare them with String.
Use a JSON library (Jackson, GSON or anything)to represent these data and also to compare them (equals() is generally overridden).It will compare them more cleanly and more specifically by considering or ignoring things like whitespace, node order and so forth...
You can find some examples here.
You could consider more particularly SkyScreamer library that provides multiple flavors to compare JSON. For example this JSONAssert.assertEquals() overload :
public static void assertEquals(org.json.JSONArray expected,
org.json.JSONArray actual,
JSONCompareMode compareMode)
throws org.json.JSONException
where you can specify a JSONCompareMode object such as JSONCompareMode.LENIENT.
170k is not too large for a String, though it is large for a string literal in source code.
Load your two strings from files that contain them, and compare in the normal way using equals.
You mention that the strings are not text but JSON. For most purposes, you'd want to normalize your json (make the whitespace, property order and punctuation the same).

String array vs String split array [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
String s = "Hi Hello Hola";
String[] d = s.split(" ");
System.out.println(d[0] == "Hi"); // prints false
String[] e = { "Hi", "Hello", "Hola" };
System.out.println(e[0] == "Hi"); // prints true
Here we have an array d with the values Hi, Hello, and Hola. We have another array e with the same set of values.
But why does this comparison behaves differently? Why does it print false and then true?
I expected false for both! As we are comparing a string literal value with the string value by using ==.
Why is this difference?
Update Here my question is not about the comparison of String values. I'm aware of the differences between == which compares the references and equals() which compares the content of the string.
From the answers, i understand that in the second case, Hi value is interned and refers to the same object. But in the other case, split creates new values without checking the literal pool. Is it right? Am i missing anything?
The reason beeing is the compiler. At compile time the compiler does notice that the literal Hi exists twice in the code and does intern this string for your specific class.
After compilation both of your interned strings Hi are pointing to the same reference of Hi. That´s the reason why the second print results in true.
The split doesn´t know it´s result and creates new references for the corresponding Strings. That´s the reson why Hi from the split and the literal Hi are not using the same reference.
This is happening because internally when split(Pattern) matches the pattern, and finds the matching char sequences, then it uses String.substring(start,end) for creating a new String object. That is why results returned by split are false. This is code snippet from java.util.regex.Pattern.split(CharSequence input, int limit) class.
String match = input.subSequence(index, m.start()).toString();
Here the input is instance of the String class, which is passed to the Pattern.split(CharSequence, int) method.
Reference: Pattern
Trying to use '==' on strings is very unpredictable. The first time you type in "Hi" as a literal, it is saved into memory. When you then assign it into the array 'e', it uses that same saved literal for storing it in the array. When you then check to see if they are equal, it resolves as true.
I highly recommend not using '==' and use one of the many methods that are provided in Java.
System.out.println("Hi".equals(d[0]));
System.out.println("Hi".equals(e[0]));
or...
System.out.println(("Hi".compareTo(d[0]) == 0));
System.out.println(("Hi".compareTo(e[0]) == 0));

indexOf() Strange Java.util.List behaviour with duplicate Strings

I've just come across some odd behaviour I wouldn't expect from an ArrayList<String> in Java. This is coming, for sure, from my poor understanding of references in Java.
Let me show you this piece of code:
List<String> myList = new ArrayList<>();
myList.add("One");
myList.add("Two");
myList.add("Two");
myList.add("Three");
for (String s : myList){
System.out.println(myList.indexOf(s));
}
This piece of code provides the following output:
0
1
1
3
How come? I've added on purpose two Strings containing the same characters ("Two"), but the object itself shouldn't be the same. What am I misunderstanding here? I was expecting this other output:
0
1
2
3
ArrayList.indexOf() doesn't use reference equality to find the object. It uses the equals() method. Notice what the documentation says (emphasis mine):
returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
Thus, it will match on the first string that is logically equal.
EDIT:
Andremoniy's comment is absolutely right. In the case of strings literals, because they are interned, they will also happen to have the same reference. So your 2 strings "Two" are actually the same reference in this case.
System.out.println("Two" == "Two"); // will return true because they are the same reference.
It's simply because indexOf returns the first occurrence of the item in the list that is equal to the given string. See its documentation:
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
You'll have to note two points:
most probably you are using the same String-instance, since the constant "Two" gets interned, that is all occurences of this literal will refer to the same instance.
List.indexOf() doesn't compare items by == (that is object-identity) but using equals() - that is some class-defined way to compare two objects for equality (which makes perfect sense as otherwise you wouldn't be able to find something in the list unless you already have a reference to it). So even two different String-objects (e.g. created by new String("Two")) would still produce the same output.
For completeness the quote from the javadoc of indexOf(as already mentioned in the other answers:
returns the lowest index i such that (o==null ? get(i)==null :
o.equals(get(i))), or -1 if there is no such index.
Java doesn't allow you to make a distinction between these two, but you have stumbled across the difference between (and disparity between) a method and a function.
Simply put a method may change the state of an object. A function will not. So calling your method add(String) will change the state of the List. Specifically, it adds the String to the list. indexOf(String) however is not a method, it is a function. Now sure, Java calls them methods because... that's what they call them. And it's conceivable that the implementation --could-- change the state. But we know that it doesn't, by contract.
A function, given the same inputs (of which the current state of the underlying object is part of those inputs) will always return the same result. Always. That's what's great about a function. You can call a function (a true function) as many times as you want and always get the same result as long as your inputs and the underlying data haven't changed.
Some folks at MIT did research into the analysis of functions in Java (which to avoid confusion, they call "pure methods"). It would be nice if there was a framework that allowed you to specify that a particular method was indeed a function (or as they call it, was pure) and then have an analyzer make sure you didn't accidentally introduce a mutation into code protected by that annotation.

mysql varchar does not compute with java string [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 8 years ago.
my case:
I try to get a value from my MySQL database. This data is defined as a VARCHAR.
This is done in java with a prepared statement and resultset.
String add1 =rs.getString("include");
according to this website table 5.1 states "Can always be converted to these Java types".
therefore a VARCHAR should be able to be converted in a java.lang.string.
When i check the data type in java it indeed gives java.lang.string. So for so good.
My issue is when i try to compare this obtained "String" value to a in java defined String value they don't seem to be equal.
Let's give a simple example.
I get the (VARCHAR) value "1" from the database and store in in String add1
I want to check if this value is indeed "1" and therefore I use the following statement
if(add1=="1")
{
/* do something */
}
Only the values are , according to java, not the same. So I was curious about why this is.
I started searching why those two "Strings" are not equal.
First of I checked the length of both strings. Both came out to be 1 in length as expected.
Afterwards I checked the value of both. To see if both values where indeed the same i wanted to check their hexadecimal representance.
Both came out with the value 0x31. Still as expected.
But then why isn't my if statement accepted by java if both seem to represent the same string-hex-bin-you name it value.
In short: Why is my VARCHAR "String" obtained from a MySQL databse in java not the same as a String defined in java.
Compare values, not memory references:
if(add1.equals("1"))
{
/* do something */
}
Please see this post best answer.
You must always compare strings with the .equals method in your case it will be
add1.equals("1")
"==" or equality operator in Java is a binary operator It is good for compairing primitives like boolean, int, float "==" works fine but when it comes to compare objects it creates confusion with equals method in Java. "==" compare two objects based on memory reference. so "==" operator will return true only if two object reference it is comparing represent exactly same object otherwise "==" will return false.
String comparison is a common scenario of using both == and equals method. Since java.lang.String class override equals method, It return true if two String object contains same content but == will only return true if two references are pointing to same object.
Read more: http://javarevisited.blogspot.com/2012/12/difference-between-equals-method-and-equality-operator-java.html#ixzz3PdLbOre0
You need to compare the Strings with .equals() method. because == checks for object reference.
What is the difference between == vs equals() in Java?

if statement not working to filter empty names [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
If statement using == gives unexpected result
Hi I'm using this code to add elements to my ComboBox, and I do not want to add empty elements, here's the code:
public void elrendezesBetoltes(ArrayList<Elrendezes> ElrLista){
int i;
Elrendezes tmp;
model.removeAllElements();
model = new DefaultComboBoxModel(comboBoxItems);
for(i=0; i<ElrLista.size(); i++){
tmp = ElrLista.get(i);
if(tmp.getName()!="")comboBoxItems.add(tmp.getName()); //not working
addButton2(tmp.getSeatnum(),tmp.getCoord(),tmp.getFoglalt());
}
}
My problem is that the if statement is not working, it still adds empty names to my combobox. What am I doing wrong?
Always use equals method to compare Strings: -
if (tmp.getName()!="")
should be: -
if (!tmp.getName().equals(""))
or simply use this, if you want to check for empty string: -
if (!tmp.getName().isEmpty()) {
comboBoxItems.add(tmp.getName());
}
Use equals method to compare string. By using != operator, you are comparing the string instances, which is always going the be true as they(tmp.getName() and "") are not same string instances.
Change
tmp.getName()!=""
to
!"".equals(tmp.getName())
Putting "" as first string in comparison will take care of your null scenario as well i.e. it will not break if tmp.getName() is null.
Use equals():
if (!tmp.getName().equals(""))
Using == or != compares string references, not string contents. This is almost never what you want.
you have to compare Strings with "equals", then it will work
if(!tmp.getName().equals(""))comboBoxItems.add(tmp.getName())
you are comparing for identity (==, !=) but each String instance has its own identity, even when they are equal.
So you need to do !tmp.getName().equals("").
Generally it is considered best practice to start with the constant string first, because it will never be null: !"".equals(tmp.getName())
However, I would recommend to use apache commons lang StringUtils. It has a notEmpty() and notBlank() method that take care of null handling and also trimming.
PS: sometimes identity will work for Strings. but it should not be relied upon as it is caused by compiler or jvm optimization due to String immutability.
Use String#isEmpty()
if(!tmp.getName().isEmpty())
OR:
if(!tmp.getName().equals(""))
Always, check String equality with equals method. == operator only checks if two references point to the same String object.
Another alternative if not on Java 6 and isEmpty is unavailable is this:
if (tmp.getName.length()>0)
Checking for the length is supposed to be quicker than using .equals although tbh the potential gain is so small its not worth worrying too much about.

Categories