How to test String is null or empty?

5,346 views
Skip to first unread message

wuhaixing

unread,
Nov 29, 2011, 2:28:58 AM11/29/11
to scala-user
I usually to write in java as :
if(s != null && !s.isEmpty())

how to do this in scala?

AGYNAMIX Torsten Uhlmann

unread,
Nov 29, 2011, 2:50:34 AM11/29/11
to wuhaixing, scala-user
Hi,

You can write it the same way, or you could use Option:

(Option(s) match {
case Full(s) if (!s.isEmpty) => String filled
case _ => String was null
}

if (!Option(s).getOrElse("").isEmpty)

Basically, you're wrapping a value that potentially could be null into an Option so you don't have to specifically test against null.
For one single statement it may seem like more work, but it's more like a style of writing code, not having to explicitly guard against null but passing an Option[YourType] around…

Torsten.

Kevin Wright

unread,
Nov 29, 2011, 3:29:21 AM11/29/11
to AGYNAMIX Torsten Uhlmann, wuhaixing, scala-user
That "Full" is the sure indicator of a Lift user...
"Full(x)" and "Empty" are subclasses of Lift's "Box" type, an Option will be either "Some(x)" or "None"

More idiomatically through, you'd often avoid these subtypes entirely and write:

    Option(stringThatMayBeNull) filterNot {_.isEmpty} foreach {s => doSomethingWith(s)}


--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Ken Scambler

unread,
Nov 29, 2011, 3:54:44 AM11/29/11
to wuhaixing, scala-user
If you control the source code that provides the String -- don't use null....*ever*.  It's like farting in an elevator. 

If you need to interact with careless libraries that are handing out nulls, only then should you do as the others have suggested here and wrap it in an Option.

Ugo Matrangolo

unread,
Nov 29, 2011, 3:56:58 AM11/29/11
to Ken Scambler, wuhaixing, scala-user
Hi,

what about a good old StringUtils.isEmpty(s) from Apache Commons ??

Regards,
Ugo.

Kevin Wright

unread,
Nov 29, 2011, 4:15:26 AM11/29/11
to Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user
Because pulling in the entirety of apache commons to check if a String is null is like calling in the fire service to clean out the air after someone farted in an elevator.  It's complete overkill...

Ken Scambler

unread,
Nov 29, 2011, 4:17:49 AM11/29/11
to Ugo Matrangolo, wuhaixing, scala-user
On 29 November 2011 19:56, Ugo Matrangolo <ugo.mat...@gmail.com> wrote:
Hi,

what about a good old StringUtils.isEmpty(s) from Apache Commons ??

Let's not recommend nicotine patches before we've ruled out cold turkey!  Seriously though, I think those Apache Utils classes are part of the problem, not the solution.  Whether in Java or Scala, they pander to sloppy thinking about null-semantics, and therefore hinder good practice.

AGYNAMIX Torsten Uhlmann

unread,
Nov 29, 2011, 4:18:01 AM11/29/11
to Kevin Wright, wuhaixing, scala-user
Yeah, right. The difference always gets me confused :) Some/Full or getOrElse/openOr…

Also, I nice way to work with an Option[String] is:

for (str <- Option(s)) yield { /* only executed if s is not null */ } getOrElse ""

Torsten.

-- 
AGYNAMIX(R). Passionate Software.
Inh. Torsten Uhlmann | Buchenweg 5 | 09380 Thalheim
Phone:       +49 3721 273445
Fax:             +49 3721 273446
Mobile:       +49 151 12412427
Web:           http://www.agynamix.de

Kevin Wright

unread,
Nov 29, 2011, 4:30:29 AM11/29/11
to AGYNAMIX Torsten Uhlmann, wuhaixing, scala-user
You forgot the emptiness check:

    val str =
      for (str <- Option(s) if !str.isEmpty)
      yield str getOrElse ""

Or if you're only working with a side effect (such as println):

    for (str <- Option(s) if !str.isEmpty)
      println(str)

Ugo Matrangolo

unread,
Nov 29, 2011, 6:46:16 AM11/29/11
to Ken Scambler, wuhaixing, scala-user
Hi,

I do not think so.

Apache Commons is useless only if you do not have the habit of defensive programming. 

Apache Commons is for people that knows that we should check preconditions. If you don't then YOU are the problem not an humble jar in your classpath that wants only to help you in avoiding to waste time writing and writing again repetitive code.

Yeah, I know, is written in Java (horrible legacy code that must be rewritten in Scala ASAP as the rest of the Universe, I know) but works nicely.

Cheers,
Ugo.

Alec Zorab

unread,
Nov 29, 2011, 7:00:27 AM11/29/11
to Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user
I suspect a large number of people on this list would strongly suggest
that rather than checking preconditions, you should leverage the type
system to enforce those conditions without (fallible) programmer
intervention.

Nils Kilden-Pedersen

unread,
Nov 29, 2011, 8:47:04 AM11/29/11
to Alec Zorab, Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user
On Tue, Nov 29, 2011 at 6:00 AM, Alec Zorab <alec...@googlemail.com> wrote:
I suspect a large number of people on this list would strongly suggest
that rather than checking preconditions, you should leverage the type
system to enforce those conditions without (fallible) programmer
intervention.

Well, you have to perform the check somewhere. Not that I disagree about using more types, but even the types need to be constructed.

Nils Kilden-Pedersen

unread,
Nov 29, 2011, 8:48:06 AM11/29/11
to wuhaixing, scala-user
require(s != null && !s.trim.isEmpty, "String content required")

Razvan Cojocaru

unread,
Nov 29, 2011, 10:03:16 AM11/29/11
to Nils Kilden-Pedersen, Alec Zorab, Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user

Well – if you have to do this quite a bit, get into a habit and define yourself a nice utility method (via pimping):

 

class NZOString (s:String) {

    def nz : Boolean = s != null && s.length > 0              //  the way of the Java

    def nzo : Option[String] = if (nz) Some(s) else None // the way of the lambda

}

 

implicit def tonzo (s:String) = new NZOString (s)

 

// sample:

 

var s : String = null

 

var r = 1

 

if (s.nz) r += 1 else r -= 1

s.nzo map (s=>r+=1)

 

r

 

How can you call methods on a possible null? As long as the compiler knows the type, it will go via NZOString(s). for instance, this will bomb:

 

scala> null.nz

<console>:10: error: value nz is not a member of Null

              null.nz

                   ^

 

scala> s=null

s: String = null

 

scala> s.nz

res5: Boolean = false

 

scala> i

martin odersky

unread,
Nov 29, 2011, 10:06:26 AM11/29/11
to wuhaixing, scala-user
I'd do it exactly the same as in Java. All of the alternatives I have seen in this thread so far are (1) longer and (2) slower. But then I'd try to deal with nulls at the interfaces to Java, so that I can forget about null inside my Scala code.

Best,

 -- Martin

Rex Kerr

unread,
Nov 29, 2011, 10:24:07 AM11/29/11
to scala-user

That's just what I was about to write.  To expand a little:

If you just need to detect whether it's null, do it like Java.  But you can omit the parens on the isEmpty:
  if (s == null || s.isEmpty)

If you have a case where you need to deal with a string that may or may not be there, then it can be useful to convert it into an Option[String], but there's no advantage if all you want is the test above.  You might, however, want to do something like:
    List(Option(s1), Option(s2), Option(s3)).flatMap(_.filter(! _.isEmpty))

which will safely wrap all the nulls in the three strings (via Option), toss the empty non-null strings (filter), and finally unwrap the options that succeeded so you're left with a list of non-null, nonempty strings.

  --Rex

P.S. I would probably actually do
  List(s1,s2,s3).map(s => Option(s).filter(! _.isEmpty)).flatten
but that's just less typing to do the same thing conceptually.

Alan Burlison

unread,
Nov 29, 2011, 10:30:22 AM11/29/11
to martin odersky, wuhaixing, scala-user
On 29/11/2011 15:06, martin odersky wrote:

> I'd do it exactly the same as in Java. All of the alternatives I have seen
> in this thread so far are (1) longer and (2) slower. But then I'd try to
> deal with nulls at the interfaces to Java, so that I can forget about null
> inside my Scala code.

I'm currently writing some Scala that interfaces with the JavaMail
library, and JavaMail loves to return you nulls all over the place, uses
lots of raw types and returns objects that you have to upcast to do
anything sensible with.

I've just used 'XXX == null' as in Java for the nulls, the one that
caused a bit of head-scratching was a method that returned a raw Java
Enumeration that I wanted to use as a Scala enumeration. I ended up with:

import java.util.{Enumeration => JEnum}
import scala.collection.JavaConverters._

msg.getMatchingHeaders(headers).asInstanceOf[JEnum[Header]].asScala.foreach(...)

Which is a bit long-winded but does mean that even pretty wizened Java
APIs can be prettified for use in Scala.

--
Alan Burlison
--

Alan Burlison

unread,
Nov 29, 2011, 10:33:40 AM11/29/11
to Alan Burlison, martin odersky, wuhaixing, scala-user
gah, s/upcast/downcast/

--
Alan Burlison
--

Razvan Cojocaru

unread,
Nov 29, 2011, 11:36:13 AM11/29/11
to martin odersky, scala-user

I would say that you are right in the general case, but in this particular case, for Strings, this expression is so common in integrating with the million Java libraries out there, that we could do a lot worse than adding nz and nzo to scala.runtime.RichString…

 

Cheers,

Razie

 

From: scala...@googlegroups.com [mailto:scala...@googlegroups.com] On Behalf Of martin odersky
Sent: November-29-11 10:06 AM
To: wuhaixing
Cc: scala-user
Subject: Re: [scala-user] How to test String is null or empty?

 

 

On Tue, Nov 29, 2011 at 8:28 AM, wuhaixing <wuha...@gmail.com> wrote:

Ken Scambler

unread,
Nov 29, 2011, 5:28:56 PM11/29/11
to Ugo Matrangolo, wuhaixing, scala-user
On 29 November 2011 22:46, Ugo Matrangolo <ugo.mat...@gmail.com> wrote:
Hi,

I do not think so.

Apache Commons is useless only if you do not have the habit of defensive programming. 

Apache Commons is for people that knows that we should check preconditions. If you don't then YOU are the problem not an humble jar in your classpath that wants only to help you in avoiding to waste time writing and writing again repetitive code.

Yeah, I know, is written in Java (horrible legacy code that must be rewritten in Scala ASAP as the rest of the Universe, I know) but works nicely.

Cheers,
Ugo.

Hi Ugo,
I'm not sure if we're talking about the same thing, let me know if not, but --

Defensiveness is fine at the boundaries of your modules;   defensiveness within a module is a bad smell, indicating that it is not taking proper responsibility for constraining its state to known, correct values.  Whether in Java or Scala, null should not be one of those values. 

Since "foo != null" is already a simple and clear piece of code, it's hard to see what the Apache FooUtils methods buy you other than complacency, in that it makes it easier to hold a "nulls everywhere" mentality that has caused endless code bloat and runtime errors in Java code over the years.

Cheers,
Ken

Naftoli Gugenheim

unread,
Nov 29, 2011, 10:08:49 PM11/29/11
to Razvan Cojocaru, Nils Kilden-Pedersen, Alec Zorab, Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user
On Tue, Nov 29, 2011 at 10:03 AM, Razvan Cojocaru <p...@razie.com> wrote:

 

How can you call methods on a possible null? As long as the compiler knows the type, it will go via NZOString(s). for instance, this will bomb:

 

scala> null.nz

<console>:10: error: value nz is not a member of Null

              null.nz

                   ^



That's a compile-time error.
 

Josh Suereth

unread,
Nov 30, 2011, 8:49:58 AM11/30/11
to Naftoli Gugenheim, Razvan Cojocaru, Nils Kilden-Pedersen, Alec Zorab, Ugo Matrangolo, Ken Scambler, wuhaixing, scala-user
For this purpose I recommned the following practice:

(A) Write Scala code assuming that if someone is using "null" to represent "Not instatitated" or "Not there", then they'll send you an Option[X] instead of an X.
(B) When accepting things from Java, wrap in an Option 'wrapper' or for expression.

Yes, there will be a slight slowdown, but you need to guard somehow, and the following just looks nicer to me:

def myRealMethod(x: String, y: String, z: String)
def fromJavaMethod(x: String, y: String, z: String) = 
   (for {   
     x1 <- Option(x)
     y1 <- Option(y)
     y2 <- Option(z)
   } yield myRealMethod(x1,y1,z1)) getOrElse ""

If you're willing to use applciative syntax (available in scalaz), you can do something like:

def myRealMethod(x: String, y: String, z: String)
def fromJavaMethod(x: String, y: String, z: String) = Option(x) |@| Option(y) |@| Option(z) apply myRealMethod getOrElse ""

I'd love to see an optimisation in the compiler for option that turns this into just raw null-checks, but unfortunately, that doesn't work for AnyVal types.  In any case, this kind of wrapping takes runtime overhead no matter *where* you do it, so I'd write code that avoid it as much as possible.  i.e. Write code that assumes non-null values in Scala and wrap things coming from Java somewhere outside your critical sections.

If your code is truly in a critical section, sometimes you just have to use null. Again, you'd be surprised at how easy this is to avoid in Scala.  If you can remove *any sort* of uninitialized value checks from your critical code sections, you'll be far better performing anyway (no branches), so the wrapping technique has a bit of merit.

- Josh






Yo Eight

unread,
Nov 30, 2011, 9:34:26 AM11/30/11
to scala-user
def hasText(str: String): Boolean =
str != null && !str.isEmpty && str.forall(c => !c.isWhitespace)

should be good

- Yo Eight

Edgar Chan

unread,
Nov 30, 2011, 12:08:11 PM11/30/11
to scala...@googlegroups.com
why not

Option(s).isEmpty

The Option object does the plumbing either to determine if s is Some [String] or None


Sciss

unread,
Nov 30, 2011, 12:13:20 PM11/30/11
to scala...@googlegroups.com
Option("").isEmpty // false

the question was whether you can treat null and "" identically.

just don't use null....

Naftoli Gugenheim

unread,
Dec 1, 2011, 2:46:34 AM12/1/11
to scala...@googlegroups.com
Because that is calling Option's isEmpty method, so it's equivalent to Option(s) == None.
You could do Option(s).map(!_.isEmpty).

Reply all
Reply to author
Forward
0 new messages