2013-01-15 58 views
0

我有以下代码:斯卡拉正确使用破返回

private def hasRole(role: String): Boolean = { 
    var hasRole = false; 
    if(getUserDetails.isDefined){ 

    // getAuthorities returns java.util.Collection<GrantedAuthority> 
    val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities 
    // Wrap the collection is a Scala class 
    val authoritiesWrapper = JCollectionWrapper.apply(authorities); 
    for(authority <- authoritiesWrapper.iterator){ 
     if(authority.getAuthority == role){ 
     hasRole = true; 
     scala.util.control.Breaks.break 
     } 
    } 
    } 
    hasRole 
} 

的问题是,是scala.util.control.Breaks.break正确的方式return当我发现的作用?看起来并不适合我。

+1

那么,首先,你还没有设定休息的范围。你需要有一个'breakable {}'子句来围绕你将要破解的代码。 – adchilds

+0

另外_ <:GrantedAuthority是什么意思?我从IntelliJ的代码中得到了这一点。 < - 作为单独的问题发布。我正在从这个中删除。 – djechlin

回答

8

如果你想使用易碎的,你需要做的是像这样:

import scala.util.control.Breaks._ 
breakable { 
    for (i <- 0 to 10000) { if (i>3) break } 
} 

但是,如果你发现自己做的是时候,你可能不会使用集合库以充分的程度。尝试代替

authoritiesWrapper.iterator.exists(_.getAuthority == role) 

而且,在你给的例子,你也可以

if (authority.getAuthority == role) return true 

当选择哪个?一般来说,如果可以的话,您应该在集合库中使用控制流选项。它们通常是最快和最清晰的。等等,最快 - 为什么是这样? breakreturn(来自for或需要关闭的其他上下文 - 基本上除ifwhilematch之外的任何其他上下文)实际上会抛出捕获到的无堆栈异常;在break的情况下,它被breakable以及return的情况所捕获。创建堆栈跟踪非常缓慢,但即使是无堆栈的异常也很慢。

因此,在这种情况下使用正确的收集方法 - exists是最佳解决方案。

+0

感谢您的回答。 +1。我已经在下面的一个单独的答案中重构了我的代码。 –

0

为什么不只是return truereturn false代替hasRole

+0

最显着的原因是'return'只从方法返回。如果您在函数文字中使用它(通常是标准库中的HOF参数),则不会从该函数返回,而是从调用HOF的方法返回! –

+0

@Randall Schulz我仍然想知道我该如何打破平行集合遍历。休息不起作用。 – idonnie

+1

@idonnie:我认为在传递给并行集合HOF的“work”函数中放置一个中断并不意味着什么。如果你想要做的是“种族”几种替代和并发的代码路径到许多单一的解决方案,期货将更适合你。我似乎回想起一种使用Futures创造类似于种族对答案的并行性的模式,但我无法回想它具体是什么或我在哪里看到它。 –

1

问题是,是scala.util.control.Breaks.break正确的方式 toreturn当我找到了角色?看起来并不适合我。

因为你只是在寻找的authority.getAuthority == role第一个实例可以使用find这正是这么做的,是这样做的惯用方式。

authoritiesWrapper.iterator.find(authority => authority.getAuthority == role) 

或更简洁

authoritiesWrapper.iterator.find(_.getAuthority == role) 

这些返回Option类型,你可以从如果存在的话得到的authority值。

+0

这将返回选项[_ <:GrantedAuthority]。然后我需要用'option.isDefined'结束我的方法吗? –

+0

是的,我认为'isDefined'会提供与'for'和'scala.util.control.Breaks.break'相同的逻辑。 – Brian

1

我只能为您提供泛泛而谈,但我希望这是至少有一点帮助的......

不幸的是,你的示例代码包含免费的标识符,所以这是不可能的,我了解它做什么,而不猜测和假设。

您正在考虑错误的问题。你在这里做什么?你是一个集合的元素。使用图书馆!它具有所有现成的这种东西。

当涉及到处理Option[Something]时,首选的方法是在map之上。如果它是None,你会得到一个None。如果它是Some(thing)那么您传递给map的函数将应用于thing,结果将是Some(what-your-function-returned-for-thing)

或者,Scala常常会发现哪些新手更可口,您可以使用Option上的模式匹配来有效区分NoneSome(thing)的情况。

谈到处理Java库时,最好将Java集合的转换推送到代码的外围,并使用本地Scala集合保留大量代码惯用的Scala。

来自Java的null也是如此。尽早将它们变成Option。为方便起见,该Option(thing)工厂将变成一个thingnullNone,并在Some

附录包裹非nullthing

其结果是,你真的不应该使用这些控制流程机制在这个代码中。它们都基于异常(除return之外),与Scala强调使用函数式编程相反。该库支持您尝试使用的基本逻辑的干净,简洁,高效的实现。不要像这样对着谷物。

0

谢谢大家,基于@Rex克尔答案我现在有这样的:

private def hasRole(role: String): Boolean = { 
    var hasRole: Boolean = false; 
    if(getUserDetails.isDefined){ 
    val authorities: util.Collection[_ <:GrantedAuthority] = getUserDetails.get.getAuthorities 
    val authoritiesWrapper = JCollectionWrapper.apply(authorities); 
    hasRole = authoritiesWrapper.iterator.exists(_.getAuthority == role) 
    } 
    hasRole 
} 

这似乎外观和感觉的权利。我使用exists来查看集合中存在的角色,然后返回该结果。如果用户未定义(未登录),则默认返回false

请评论,如果这仍然不完美。

+0

'hasRole' var没有任何用处。你可以简单地删除它,然后使用if(getUserDetails ..){...} else false(而不是在if语句中设置hasRole)。 )。另外,由于'getUserDetails'是一个选项,你通常会让它执行逻辑(使用它的'exist'方法)而不是添加if/else:'hasRole(role:String)= getUserDetails.exists {ud => val auth:util.Collection [_ <:GrantedAuthority] = ud.getAuthorities; JCollectionWrapper(auth).iterator.exists(_。getAuthority == role)}' –