網頁

2019/6/24

什麼是Tuple?

Tuple是一種資料結構(data structure),是多個不同型別物件的有序集合,集合中的元素間不必有關連,但把這些元素擺在一起通常具有某種意義。

例如["Java", 1.8, "Windows"]裡面的元素彼此沒有關係,但擺在一起就看得出來是指Java的系統版本。

Java本身並沒有這種資料結構,所以要用類別來模擬Tuple。而Python則有Tuple,例如下面設定並印出Tuple的內容。

Python定義Tuple用小括弧()將元素包起,每個元素用逗號,分隔。

>>> tuple1 = ("hello", "world")
>>> tuple2 = ("Toyota", 2000, "2017")
>>> tuple3 = (1,3,5,7,9)
>>> print(tuple1)
('hello', 'world')
>>> print(tuple2)
('Toyota', 2000, '2017')
>>> print(tuple3)
(1, 3, 5, 7, 9)

Tuple雖然和List很像,都是裝載多個物件的有序集合,其差異如下:

  • Tuple中可包含多個不同型別的物件;List中為多個相同型別的物件。
  • Tuple是不可變的(Immutable),元素及結構不可被修改;List是可變的(Mutable),元素及結構可以被修改。

例如下面定義了一個Python的Tuple變數,然後試圖修改其元素內容。

>>> tuple1 = ("iPhone X", 20000)
>>> tuple1[1] = 18000
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

因為Tuple是不可變的,所以若修改內容會出現錯誤訊息。


在Java除了自己定義類別來實做Tuple,可以直接用javatuples套件,Maven依賴如下。

<!-- https://mvnrepository.com/artifact/org.javatuples/javatuples -->
<dependency>
    <groupId>org.javatuples</groupId>
    <artifactId>javatuples</artifactId>
    <version>1.2</version>
</dependency>

javatuples提供了以下Tuple類別,分別裝載1到10個指定型別的元素。

  • Unit<A> (1 element)
  • Pair<A,B> (2 elements)
  • Triplet<A,B,C> (3 elements)
  • Quartet<A,B,C,D> (4 elements)
  • Quintet<A,B,C,D,E> (5 elements)
  • Sextet<A,B,C,D,E,F> (6 elements)
  • Septet<A,B,C,D,E,F,G> (7 elements)
  • Octet<A,B,C,D,E,F,G,H> (8 elements)
  • Ennead<A,B,C,D,E,F,G,H,I> (9 elements)
  • Decade<A,B,C,D,E,F,G,H,I,J> (10 elements)

例外提供兩個與Pair一樣裝載兩個元素的類別,其名稱比較符合意義。

  • KeyValue<A,B> (1 element)
  • LabelValue<A,B> (2 elements)

javatuples的Tuple類別具有以下特色:

  • 型別安全(Typesafe)
  • 不可變的(Immutable)
  • 可遍歷(Iterable)
  • 可序列化(Serializable)
  • 可比較,實作了Comparable
  • 實作了equals()hashCode()
  • 實作了toString()


以下為Tuple類別的一些簡單用法,可以用建構式或工廠方法with()來產生物件。

Unit<Integer> unit = new Unit<>(1);
Pair<String, String> pair = Pair.with("hello", "world");
Triplet<String, Integer, String> triplet = new Triplet<>("Toyota", 2000, "Japan");
Quartet<Integer, Integer, Integer, Integer> quartet = Quartet.with(1, 2, 3, 5);

System.out.println(unit);    // [1]
System.out.println(pair);    // [hello, world]
System.out.println(triplet); // [Toyota, 2000, Japan]
System.out.println(quartet); // [1, 2, 3, 5]

System.out.println(pair.getValue0()); // hello
System.out.println(pair.getValue(1)); // world
pair = pair.setAt1("tuple");  // 回傳新的物件
System.out.println(pair);             // [hello, tuple]

由於Tuple類別是不可變的,所以呼叫setAtX()方法回傳的是新的Tuple物件。


不過在Java使用Tuple前,仔細想想為什麼Java沒有提供Tuple呢?因為Java的類別本身就是一種可以讓你自由定義任何型別的一種"Tuple"容器,因為這樣所以Java其實不用特別去使用Tuple,直接用定義好的類別就好了。


參考:

沒有留言:

張貼留言