起因:在写java的时候,经常遇到函数需要返回2个值或者3个值,java必须编写一个Object,来封装,但很多应用场景只是临时使用,构建对象感觉杀鸡用宰牛刀,而其他语言有比较好的实现方法。(当然通过指针引用可以解决一部分问题)
如:一般写法:
public class Tt {
public static void main(String[] args) {
Tt t = new Tt();
User user = t.getUser();
long id = user.getId();
String name = user.getName();
// TODO .. do something
}
public User getUser() {
// 测试
User user = new User();
user.setId(1L);
user.setName("hello");
return user;
}
class User {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
使用Tuple来实现:
public class Tt {
public static void main(String[] args) {
Tt t = new Tt();
Tuple2<Long, String> user = t.getUser();
long id = user._1();
String name = user._2();
// TODO ..do something
}
private Tuple2<Long, String> getUser() {
long id = 1L;
String name = "hello";
return Tuple.tuple(id, name);
}
}
Tuple类:
import java.io.Serializable;
public abstract class Tuple implements Serializable {
/** *//**
* gen by eclipse
*/
private static final long serialVersionUID = -8719929625763890308L;
public static <A, B> Tuple2<A, B> tuple(A a, B b) {
return new Tuple2<A, B>(a, b);
}
public static <A, B, C, D, E> Tuple3<A, B, C> tuple(A a, B b, C c) {
return new Tuple3<A, B, C>(a, b, c);
}
public static final class Tuple2<A, B> extends Tuple implements Serializable {
/** *//**
* gen by eclipse
*/
private static final long serialVersionUID = 7263645006696591635L;
private A a;
private B b;
private Tuple2(A a, B b) {
this.a = a;
this.b = b;
}
public A _1() {
return this.a;
}
public B _2() {
return this.b;
}
}
public static final class Tuple3<A, B, C> extends Tuple implements Serializable {
/** *//**
* gen by eclipse
*/
private static final long serialVersionUID = 482545776907024160L;
private A a;
private B b;
private C c;
private Tuple3(A a, B b, C c) {
this.a = a;
this.b = b;
this.c = c;
}
public A _1() {
return this.a;
}
public B _2() {
return this.b;
}
public C _3() {
return this.c;
}
}
}
note: 1、这里只是写了2,3,如果有需要直接扩展实现就可以了
2、这里的Tuple类其实没多大用处,都可以直接使用Tuple2, Tuple3,但为了方便统一从Tuple入口出去,创建了静态方法。这样写更具扩展性。
Tuple:
用来表示一组单独的数据,比如数据库中的一条记录;这一点很好理解哈,Tuple的每个Item就像一条记录的每个字段。
当我们希望函数返回多个值的时候,我们可以使用Tuple类型作为函数的返回值,这样我们就可以不用ref来定义多个参数了
Python中的Tuple类型 介绍:
Tuple 是不可变 list。 一旦创建了一个 tuple 就不能以任何方式改变它。
Tuple 与 list 的相同之处
- 定义 tuple 与定义 list 的方式相同, 除了整个元素集是用小括号包围的而不是方括号。
- Tuple 的元素与 list 一样按定义的次序进行排序。 Tuples 的索引与 list 一样从 0 开始, 所以一个非空 tuple 的第一个元素总是 t[0]。
- 负数索引与 list 一样从 tuple 的尾部开始计数。
- 与 list 一样分片 (slice) 也可以使用。注意当分割一个 list 时, 会得到一个新的 list ;当分割一个 tuple 时, 会得到一个新的 tuple。
Tuple 不存在的方法
- 不能向 tuple 增加元素。Tuple 没有 append 或 extend 方法。
- 不能从 tuple 删除元素。Tuple 没有 remove 或 pop 方法。
- 您不能在 tuple 中查找元素。Tuple 没有 index 方法。
- 然而, 您可以使用 in 来查看一个元素是否存在于 tuple 中。
用 Tuple 的好处
- Tuple 比 list 操作速度快。如果定义了一个值的常量集,并且唯一要用它做的是不断地遍历它,请使用 tuple 代替 list。
- 如果对不需要修改的数据进行 “写保护”,可以使代码更安全。使用 tuple 而不是 list 如同拥有一个隐含的 assert 语句,说明这一数据是常量。如果必须要改变这些值,则需要执行 tuple 到 list 的转换。
Tuple 与 list 的转换
Tuple 可以转换成 list,反之亦然。内置的 tuple 函数接收一个 list,并返回一个有着相同元素的 tuple。而 list 函数接收一个 tuple 返回一个 list。从效果上看,tuple 冻结一个 list,而 list 解冻一个 tuple。
Tuple 的其他应用
一次赋多值
>>> v = ('a', 'b', 'e')
>>> (x, y, z) = v
解释:v 是一个三元素的 tuple, 并且 (x, y, z) 是一个三变量的 tuple。将一个 tuple 赋值给另一个 tuple, 会按顺序将 v 的每个值赋值给每个变量。
Microsoft在MSDN中对Tuple的描述是“A tuple is a data structure that has a specific number and sequence of values.”,由于E文水平有限,我理解的大概意思就是:Tuple是具有指定数量和顺序的值的一种数据结构。针对这种数据结构,.Net4.0中提供了一组Tuple类型,具体如下:
Tuple |
|
Tuple<T> |
|
Tuple<T1, T2> |
|
Tuple<T1, T2, T3> |
|
Tuple<T1, T2, T3, T4> |
|
Tuple<T1, T2, T3, T4, T5> |
|
Tuple<T1, T2, T3, T4, T5, T6> |
|
Tuple<T1, T2, T3, T4, T5, T6, T7> |
|
Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> |
|
通过这些Tuple类型的声明我们可以看出.Net4.0中提供了从包含1个值到最多8个值的Tuple,我们可以通过第一个Tuple的静态方法 Create来创建一个泛型Tuple<>的实例,例如Tuple<string, int> t = Tuple.Create("key", 789); 也可以使用泛型Tuple的构造函数来创建实例,例如Tuple<string, int> t = new Tuple<string, int>("key", 324);
知道了Tuple类型的定义后,我们什么时候会用到它呢?对于Tuple<T>来说,我觉得我们大多数时候都不会使用这样一个数据类型将一个实际要用的类型包装起来,然后进行调用。(有些人提到Tuple类型用来和F#等语言进行交互,我不是很了解关于F#的细节,或许是在与F#交互的时候能够用到吧),抛开Tuple<T>不说,其它的Tuple<>类型为我们的程序开发带来了极大的方便。以前当我们需要处理若干相关数据的时候,例如员工ID、员工年龄和员工入职时间,为了编程的结构合理,我们会定义一个新的员工类,让它包含ID、年龄和入职时间等属性(当然,你也可以分别声明3个变量),现在,我们只需要声明一个Tuple<string, int, DateTime>的对象即可,省去了定义一个新类的步骤,当然,我们这么做是以牺牲代码的可读性为代价的,毕竟我们访问Tuple对象的时候是通过类似Item这样的没有实际含义的属性来访问它的成员的。