0

I got this code from https://github.com/Netflix/astyanax/wiki/Cql-and-cql3

I'm new to scala and my problem is to convert this for loop to a scala one.

Could you please help ?

result = keyspace
        .prepareQuery(CQL3_CF)
        .withCql("SELECT * FROM employees WHERE empId='111';")
        .execute();

for (Row<Integer, String> row : result.getResult().getRows()) {
    LOG.info("CQL Key: " + row.getKey());

    ColumnList<String> columns = row.getColumns();

    LOG.info("   empid      : " + columns.getIntegerValue("empid",      null));
    LOG.info("   deptid     : " + columns.getIntegerValue("deptid",     null));
    LOG.info("   first_name : " + columns.getStringValue ("first_name", null));
    LOG.info("   last_name  : " + columns.getStringValue ("last_name",  null));
} 

Many thanks

4

1 回答 1

3

将此代码转换为基于 scala 的循环构造的一种方法如下:

  import scala.collection.JavaConversions._

  val result = keyspace
    .prepareQuery(CQL3_CF)
    .withCql("SELECT * FROM employees WHERE empId='111';")
    .execute();  

  result.getResult().getRows() foreach { row =>
    LOG.info("CQL Key: " + row.getKey())

    val columns = row.getColumns()

    LOG.info("   empid      : " + columns.getIntegerValue("empid",      null))
    LOG.info("   deptid     : " + columns.getIntegerValue("deptid",     null))
    LOG.info("   first_name : " + columns.getStringValue ("first_name", null))
    LOG.info("   last_name  : " + columns.getStringValue ("last_name",  null))    
  }

通过导入 JavaConversions._,我们可以访问一个隐式转换,它将 Java Iterable(即 Rows 对象)转换为 a scala.collection.Iterable,从而允许您使用foreach循环构造。

现在,这段代码在语法上是合理的,但它并不是真正好的 Scala 代码。它不是很实用,因为循环本身不返回任何东西。它还有一些处理空值的混乱逻辑,可能应该使用 Options 来代替。一个更实用的解决方案示例,map用于将结果数据映射到一个简单的案例类,如下所示:

import scala.collection.JavaConversions._

val result = keyspace
  .prepareQuery(CQL3_CF)
  .withCql("SELECT * FROM employees WHERE empId='111';")
  .execute(); 

case class Employee(id:Option[Int], depId:Option[Int], 
  firstName:Option[String], lastName:Option[String])

def optFor[T](cl:ColumnList[String], func:(ColumnList[String] => T)):Option[T] = {
  func(cl) match{
    case null => None
    case nonnull => Some(nonnull)
  }
}

val employees = result.getResult().getRows() map { row =>
  LOG.info("CQL Key: " + row.getKey())
  val cl = row.getColumns()
  val employee = Employee(optFor(cl, _.getIntegerValue("empid", null)), 
    optFor(cl, _.getIntegerValue("deptid", null)), 
    optFor(cl, _.getStringValue("first_name", null)), 
    optFor(cl, _.getStringValue("last_name", null)))

  LOG.info(employee)
  employee
}

可能有一种更优雅的方式来处理 null 到Option转换(也许通过隐式),但这也有效。完成map操作后,您将拥有一个scala.collection.Iterable实例Employee,然后您可能会返回到 UI 进行显示。

于 2013-04-23T12:51:53.470 回答