Java 8有一个全新的日期和时间API.此API中最有用的类之一是LocalDateTime
,用于保存与时区无关的日期时间值.
java.util.Date
为此目的,使用遗留类可能有数百万行代码.因此,当连接新旧代码时,需要在两者之间进行转换.由于似乎没有直接的方法来实现这一点,怎么办呢?
如果我有一个简单的字符串列表:
List<String> stringList = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)
我可以用它来分类:
Collections.sort(stringList);
Run Code Online (Sandbox Code Playgroud)
但是假设我有一个Person类:
public class Person
{
private String name;
private Integer age;
private String country;
}
Run Code Online (Sandbox Code Playgroud)
并列出一个:
List<Person> personList = new ArrayList<Person>();
Run Code Online (Sandbox Code Playgroud)
我希望有时按名字排序,有时按年龄,有时按国家排序.
最简单的方法是什么?
我知道我可以实现Comparable接口,但这似乎限制我按一个特定属性对其进行排序.
鉴于:
case class Foo(a: Int, b: String, c: Double)
Run Code Online (Sandbox Code Playgroud)
你可以说:
val params = Foo(1, "bar", 3.14).productIterator.toList
Run Code Online (Sandbox Code Playgroud)
得到:
params: List[Any] = List(1, bar, 3.14)
Run Code Online (Sandbox Code Playgroud)
有没有办法"向后"并直接从此列表重新创建Foo对象,即:
Foo.createFromList(params) // hypothetical
Run Code Online (Sandbox Code Playgroud)
而不是写:
Foo(params(0).asInstanceOf[Int], params(1).asInstanceOf[String], params(2).asInstanceOf[Double])
Run Code Online (Sandbox Code Playgroud)
编辑:似乎它归结为能够将列表的元素作为参数发送到函数而不显式写出来,例如:
def bar(a: Int, b: Int, c: Int) = //...
val list = List(1, 2, 3, 4, 5)
bar(list.take(3)) // hypothetical, instead of:
bar(list(0), list(1), list(2))
Run Code Online (Sandbox Code Playgroud)
我希望能做到:
bar(list.take(3): _*)
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用.
编辑:解决方案基于extempore的答案,但直接调用构造函数而不是使用apply方法:
case class Foo(a: Int = 0, b: String = "bar", c: Double = 3.14) {
val cs = …
Run Code Online (Sandbox Code Playgroud) 说我有一个val s: Option[Option[String]]
.因此它可以具有以下值:
Some(Some("foo"))
Some(None)
None
我想减少它,以便第一个成为Some("foo")
另外两个成为None
.很明显,有很多方法可以实现这一目标,但我正在寻找一种简单的,可能是内置的,不足一线的.
这可能是一个天真的问题.我目前正在学习Spring框架和依赖注入.虽然DI的基本原理很容易掌握,但是为什么需要一个精心设计的框架来实现它并不是很明显.
考虑以下:
public abstract class Saw
{
public abstract void cut(String wood);
}
public class HandSaw extends Saw
{
public void cut(String wood)
{
// chop it up
}
}
public class ChainSaw extends Saw
{
public void cut(String wood)
{
// chop it a lot faster
}
}
public class SawMill
{
private Saw saw;
public void setSaw(Saw saw)
{
this.saw = saw;
}
public void run(String wood)
{
saw.cut("some wood");
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地做:
Saw saw = …
Run Code Online (Sandbox Code Playgroud) 你可以写:
str match { case "foo" | "bar" => ... }
Run Code Online (Sandbox Code Playgroud)
乍一看,它看起来|
可能是一个提取器对象,但是:
str match { case |("foo", "bar") => ... }
Run Code Online (Sandbox Code Playgroud)
不起作用.(我无法看到无论如何都可以实现.)
那么它是一个神奇的内置运营商?
(我相信我之前已经在SO上看过这个问题了,但是找不到......)
鉴于:
case class Person(name: String)
Run Code Online (Sandbox Code Playgroud)
并尝试做:
scala> List(Person("Tom"), Person("Bob")).sorted
Run Code Online (Sandbox Code Playgroud)
导致对失踪订购的投诉.
<console>:8: error: could not find implicit value for parameter ord: Ordering[Person]
List(Person("Tom"), Person("Bob")).sorted
Run Code Online (Sandbox Code Playgroud)
不过这个:
case class Person(name: String) extends Ordered[Person] {
def compare(that: Person) = this.name compare that.name }
Run Code Online (Sandbox Code Playgroud)
按预期工作正常:
scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))
Run Code Online (Sandbox Code Playgroud)
虽然没有涉及订购或暗示.
问题1:这里发生了什么?(我的钱是隐含的......)
但是,考虑到上述事实,这个事实:
scala> Person("Tom") > Person("Bob")
res15: Boolean = true
Run Code Online (Sandbox Code Playgroud)
工作,这也是:
scala> List(Some(2), None, Some(1)).sorted
Run Code Online (Sandbox Code Playgroud)
开箱即用:
res13: List[Option[Int]] = List(None, Some(1), Some(2))
Run Code Online (Sandbox Code Playgroud)
我希望这个:
scala> Some(2) > Some(1)
Run Code Online (Sandbox Code Playgroud)
也会有效,但不会:
<console>:6: error: …
Run Code Online (Sandbox Code Playgroud) 假设您定义以下内容:
class Person(name: String, age: Int) {
def toXml =
<person>
<name>{ name }</name>
<age>{ age }</age>
</person>
}
val Persons = List(new Person("John", 34), new Person("Bob", 45))
Run Code Online (Sandbox Code Playgroud)
然后生成一些XML并将其保存到文件中:
val personsXml =
<persons>
{ persons.map(_.toXml) }
</persons>
scala.xml.XML.save("persons.xml", personsXml)
Run Code Online (Sandbox Code Playgroud)
你最终得到了以下有趣的文字:
<persons>
<person>
<name>John</name>
<age>32</age>
</person><person>
<name>Bob</name>
<age>43</age>
</person>
</persons>
Run Code Online (Sandbox Code Playgroud)
当然,现在,这是完全有效的XML,但是如果你想在一个体面的文本编辑器中进行人工编辑,那么最好将它格式化得更好一些.
通过更改Scala XML文字的各个点上的缩进 - 使代码看起来不那么好 - 可以生成上述输出的变体,但似乎不可能完全正确.我理解为什么它会以这种方式格式化,但想知道是否有任何方法可以解决它.
鉴于例如:
List(5, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
Run Code Online (Sandbox Code Playgroud)
我想去:
List(List(5), List(2), List(3, 3, 3), List(5, 5), List(3, 3), List(2, 2, 2))
Run Code Online (Sandbox Code Playgroud)
我会假设有一个简单的List函数来执行此操作,但我无法找到它.
我知道类型擦除使它们在运行时看起来相同,类型,所以:
class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}
Run Code Online (Sandbox Code Playgroud)
给出以下编译器错误:
<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^
Run Code Online (Sandbox Code Playgroud)
但是有一种简单的方法可以写:
bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)
Run Code Online (Sandbox Code Playgroud)
并让这些调用foo的不同重载版本,而不必明确命名它们:
bar.fooInts(1, 2, …
Run Code Online (Sandbox Code Playgroud) scala ×7
java ×3
collections ×2
datetime ×1
flatten ×1
java-8 ×1
java-time ×1
join ×1
monads ×1
option ×1
overloading ×1
sorting ×1
spring ×1
type-erasure ×1