• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

predicates

 
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


in the below code, how is the generic type for the Predicate determined , is it through line A ?
because i see that in line A, if i don't use generics to specify String type then line B shows an error !
List<String> bunnies = new ArrayList<>(); //line A
bunnies.add("long ear");
bunnies.add("floppy");
bunnies.add("hoppy");
System.out.println(bunnies); // [long ear, floppy, hoppy]
bunnies.removeIf(s -> s.charAt(0) != 'h'); //line B
System.out.println(bunnies); // [hoppy]

when we we use predicates generally, we are supposed to specify the type right ? otherwise how how java know which class type it has to handle?
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
bunnies is a List of String, and therefore the removeIf() method in line B expects a lamda expression that takes a String - so that is how the type of the variable s is inferred to be String.

If you don't use generics, and you use the raw type List instead, then you just have a list of objects - the compiler doesn't know that it's a list that is supposed to contain only strings, and then the type of s will be inferred to be Object.

Note: You should not use raw types. Always use generics. The only reason that raw types exist is for backward compatibility with old version of Java (Java 1.4 and older). You should only use raw types if it is absolutely necessary, because you are dealing with old code that you cannot change.
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
so the only way that the removeIf() method determines the type of generic for the predicate , is by the type of the ArrayList right ?
 
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No. You can also explicitly specify the type of the lambda's parameters:
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And in the case of methods that have additional type parameters, you can supply type arguments explicitly:
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Stephan van Hulst wrote:No. You can also explicitly specify the type of the lambda's parameters:






but if i make the change on line 1 by removing the String generic type, line 6 shows an error !
 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

shambhavi sham wrote:
but if i make the change on line 1 by removing the String generic type, line 6 shows an error ! [/b]



It generates a compiler error because, as Stephan mentioned, the type is specified. And the error is a type mismatch. If you didn't specify the type, then the type would be inferred, and the code will compile.

Keep in mind, that your previous question implied that specifying the type is not an option. Just because you found a case, where you specified the type, and it generates an error, doesn't mean that specifying the type is not an option...

So, you can specify the type -- but you also need to do so without causing a type mismatch.

Henry
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


in the above code , Object and String are causing a mismatch even though String inherits from Object.

but in the below code CharSequence and String don't show any such mismatch . may i know why ?
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Except you don't have an ArrayList<Object>. You have a raw ArrayList. That means removeIf() accepts a raw Predicate. You can't use a lambda expression for a raw Predicate.
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
uh no i don't get you ! can you be more clear please.

 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How does the compiler know that bunnies is full of Strings? What if I added the following line?
The lambda you passed can not deal with integers, so the compiler is giving off an error.
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
my query deals with these two lines .

CASE 1 : NO ERROR

List<String> bunnies = new ArrayList<>();
bunnies.removeIf((CharSequence s) -> s.charAt(0) != 'h');


CASE 2 : ERROR

List<CharSequence> bunnies = new ArrayList<>();
bunnies.removeIf((String s) -> s.charAt(0) != 'h'); //error



CASE 3 : ERROR
List bunnies = new ArrayList();
bunnies.removeIf((String s) -> s.charAt(0) != 'h'); //error




 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

shambhavi sham wrote:
CASE 1 : NO ERROR

List<String> bunnies = new ArrayList<>();
bunnies.removeIf((CharSequence s) -> s.charAt(0) != 'h');



All String instances are IS-A CharSequence instances.

shambhavi sham wrote:
CASE 2 : ERROR

List<CharSequence> bunnies = new ArrayList<>();
bunnies.removeIf((String s) -> s.charAt(0) != 'h'); //error



All CharSequences instances may *not* be IS-A String instances.

shambhavi sham wrote:
CASE 3 : ERROR
List bunnies = new ArrayList();
bunnies.removeIf((String s) -> s.charAt(0) != 'h'); //error



Raw collections, which deals with Object instances ... and all Object instances may *not* be IS-A String instances.

Henry
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks henry, stephan and jesper !          

bunnies is a List of String, and therefore the removeIf() method in line B expects a lamda expression that takes a String - so that is how the type of the variable s is inferred to be String. this line was in Jesper's answer to my question in this thread. i just want to confirm ,  instead of removeIf() if i were to call some other user defined method that takes a raw Predicate as argument, then where would i have to specify the type i wish to use ? in this case too will it be determined by the object on which this method is called ?

 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let's do that now.

Now, a raw type is basically the same thing as a parameterized type that uses an unbounded wildcard, except that the compiler doesn't enforce type safety. That means that when you call applyRawPredicate(), you should treat the parameter as a Predicate<?>. The only thing you know for sure about the actual type argument is that it's an Object (because all types inherit from Object). When you want to supply a lambda expression for such a parameter, the lambda's parameter has to be of type Object, and then you'll have to cast it to whatever type you need to deal with:

As you can see, there is no type safety here (what if we had cast to Integer instead?), and the code is just hard to understand and deal with. The lesson? NEVER USE RAW GENERIC TYPES.
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
do you have a similar definition of the removeIf() method ?
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't understand what you mean. Do you want to see how I would implement the removeIf() method if the parameter was a raw predicate?
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
no i want to see when ArrayList<String> arr=new ArrayList();  object is created and then used to call the removeIf() method , how its type is inferred in its constructor ?
 
Stephan van Hulst
Saloon Keeper
Posts: 15510
363
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The constructor has no relation to the removeIf() method. You declared arr as an ArrayList<String>, so all occasions of E in the class are substituted with with String. That means that the method signature becomes removeIf(Predicate<String> filter).

There is no type inferred in the constructor call, because you used a raw type again.
 
blossom belle
Ranch Hand
Posts: 145
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK  
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic