commons-lang3的tuple包介紹

問(wèn)題

有時(shí)候我們調(diào)用方法的時(shí)候返回值有可能不止1個(gè),比如說(shuō)我們返回name = "張三" age = 20這兩個(gè)值咧虎,那么這個(gè)時(shí)候方法的返回值怎么寫(xiě)呢庸疾。在Scala和python中都有Tuple使用,在java中我們?cè)趺崔k睡互。很容易我們就想到了一個(gè)方式:可以構(gòu)造一個(gè)User類來(lái)封裝這兩個(gè)屬性肠套。
但是如果返回的兩個(gè)值并沒(méi)有任何關(guān)聯(lián)關(guān)系舰涌,或者說(shuō)每一個(gè)方法返回的參數(shù)都不同,那么我們就得為每一個(gè)方法的返回類型去創(chuàng)建對(duì)應(yīng)的類來(lái)取包裝你稚,或許還有其他的解決方式瓷耙,比如說(shuō)返回一個(gè)map,返回一個(gè)List刁赖,返回一個(gè)array都可以搁痛。
使用map作為返回值的話調(diào)用方在不清楚map中具體有什么內(nèi)容的時(shí)候需要去遍歷keySet或entrySet,而list和array也是同樣的問(wèn)題,不知道哪一個(gè)參數(shù)存放在哪里宇弛。

解決方式

其實(shí)前人已經(jīng)為我們解決了這個(gè)問(wèn)題鸡典。
如果你經(jīng)常使用apache的commons-lang3包來(lái)處理String的null判斷,那么你依舊可以從這個(gè)包中找到我們想要的一個(gè)所謂的元組枪芒。
org.apache.commons.lang3.tuple.Pair


/**
 * <p>A pair consisting of two elements.</p>
 *
 * <p>This class is an abstract implementation defining the basic API.
 * It refers to the elements as 'left' and 'right'. It also implements the
 * {@code Map.Entry} interface where the key is 'left' and the value is 'right'.</p>
 *
 * <p>Subclass implementations may be mutable or immutable.
 * However, there is no restriction on the type of the stored objects that may be stored.
 * If mutable objects are stored in the pair, then the pair itself effectively becomes mutable.</p>
 *
 * @param <L> the left element type
 * @param <R> the right element type
 *
 * @since Lang 3.0
 */
public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {

    /** Serialization version */
    private static final long serialVersionUID = 4954918890077093841L;

    /**
     * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
     *
     * <p>This factory allows the pair to be created using inference to
     * obtain the generic types.</p>
     *
     * @param <L> the left element type
     * @param <R> the right element type
     * @param left  the left element, may be null
     * @param right  the right element, may be null
     * @return a pair formed from the two parameters, not null
     */
    public static <L, R> Pair<L, R> of(final L left, final R right) {
        return new ImmutablePair<>(left, right);
    }

    //-----------------------------------------------------------------------
    /**
     * <p>Gets the left element from this pair.</p>
     *
     * <p>When treated as a key-value pair, this is the key.</p>
     *
     * @return the left element, may be null
     */
    public abstract L getLeft();

    /**
     * <p>Gets the right element from this pair.</p>
     *
     * <p>When treated as a key-value pair, this is the value.</p>
     *
     * @return the right element, may be null
     */
    public abstract R getRight();

    /**
     * <p>Gets the key from this pair.</p>
     *
     * <p>This method implements the {@code Map.Entry} interface returning the
     * left element as the key.</p>
     *
     * @return the left element as the key, may be null
     */
    @Override
    public final L getKey() {
        return getLeft();
    }

    /**
     * <p>Gets the value from this pair.</p>
     *
     * <p>This method implements the {@code Map.Entry} interface returning the
     * right element as the value.</p>
     *
     * @return the right element as the value, may be null
     */
    @Override
    public R getValue() {
        return getRight();
    }

    //-----------------------------------------------------------------------
    /**
     * <p>Compares the pair based on the left element followed by the right element.
     * The types must be {@code Comparable}.</p>
     *
     * @param other  the other pair, not null
     * @return negative if this is less, zero if equal, positive if greater
     */
    @Override
    public int compareTo(final Pair<L, R> other) {
      return new CompareToBuilder().append(getLeft(), other.getLeft())
              .append(getRight(), other.getRight()).toComparison();
    }

    /**
     * <p>Compares this pair to another based on the two elements.</p>
     *
     * @param obj  the object to compare to, null returns false
     * @return true if the elements of the pair are equal
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj instanceof Map.Entry<?, ?>) {
            final Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
            return Objects.equals(getKey(), other.getKey())
                    && Objects.equals(getValue(), other.getValue());
        }
        return false;
    }

    /**
     * <p>Returns a suitable hash code.
     * The hash code follows the definition in {@code Map.Entry}.</p>
     *
     * @return the hash code
     */
    @Override
    public int hashCode() {
        // see Map.Entry API specification
        return (getKey() == null ? 0 : getKey().hashCode()) ^
                (getValue() == null ? 0 : getValue().hashCode());
    }

    /**
     * <p>Returns a String representation of this pair using the format {@code ($left,$right)}.</p>
     *
     * @return a string describing this object, not null
     */
    @Override
    public String toString() {
        return new StringBuilder().append('(').append(getLeft()).append(',').append(getRight()).append(')').toString();
    }

    /**
     * <p>Formats the receiver using the given format.</p>
     *
     * <p>This uses {@link java.util.Formattable} to perform the formatting. Two variables may
     * be used to embed the left and right elements. Use {@code %1$s} for the left
     * element (key) and {@code %2$s} for the right element (value).
     * The default format used by {@code toString()} is {@code (%1$s,%2$s)}.</p>
     *
     * @param format  the format string, optionally containing {@code %1$s} and {@code %2$s}, not null
     * @return the formatted string, not null
     */
    public String toString(final String format) {
        return String.format(format, getLeft(), getRight());
    }

}

這個(gè)類構(gòu)建了一個(gè)由兩個(gè)元素組成的一個(gè)元組彻况,leftright兩個(gè)元素谁尸。
繼承了Map.Entry,可以使用getKey()getValue()方法疗垛,從源碼中我們也發(fā)現(xiàn)其實(shí)是調(diào)用了他本身的getLeft()getRight()方法,而這兩個(gè)方法是需要子類去實(shí)現(xiàn)硫朦,我們后面說(shuō)贷腕。
繼承了Comparable,可以比較兩個(gè)Pair咬展。
繼承了Serializable泽裳,可以被序列化。
比較重要的就是getKey()getValue()破婆,下面我們看這個(gè)類的兩個(gè)實(shí)現(xiàn)ImmutablePairMutablePair涮总。

ImmutablePair很好理解,不可變的Pair祷舀,相對(duì)的MutablePair就是可變的Pair

先看ImmutablePair.class


/**
 * <p>An immutable pair consisting of two {@code Object} elements.</p>
 *
 * <p>Although the implementation is immutable, there is no restriction on the objects
 * that may be stored. If mutable objects are stored in the pair, then the pair
 * itself effectively becomes mutable. The class is also {@code final}, so a subclass
 * can not add undesirable behaviour.</p>
 *
 * <p>#ThreadSafe# if both paired objects are thread-safe</p>
 *
 * @param <L> the left element type
 * @param <R> the right element type
 *
 * @since Lang 3.0
 */
public final class ImmutablePair<L, R> extends Pair<L, R> {

    /**
     * An immutable pair of nulls.
     */
    // This is not defined with generics to avoid warnings in call sites.
    @SuppressWarnings("rawtypes")
    private static final ImmutablePair NULL = ImmutablePair.of(null, null);

    /** Serialization version */
    private static final long serialVersionUID = 4954918890077093841L;

    /**
     * Returns an immutable pair of nulls.
     *
     * @param <L> the left element of this pair. Value is {@code null}.
     * @param <R> the right element of this pair. Value is {@code null}.
     * @return an immutable pair of nulls.
     * @since 3.6
     */
    @SuppressWarnings("unchecked")
    public static <L, R> ImmutablePair<L, R> nullPair() {
        return NULL;
    }

    /** Left object */
    public final L left;
    /** Right object */
    public final R right;

    /**
     * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
     *
     * <p>This factory allows the pair to be created using inference to
     * obtain the generic types.</p>
     *
     * @param <L> the left element type
     * @param <R> the right element type
     * @param left  the left element, may be null
     * @param right  the right element, may be null
     * @return a pair formed from the two parameters, not null
     */
    public static <L, R> ImmutablePair<L, R> of(final L left, final R right) {
        return new ImmutablePair<>(left, right);
    }

    /**
     * Create a new pair instance.
     *
     * @param left  the left value, may be null
     * @param right  the right value, may be null
     */
    public ImmutablePair(final L left, final R right) {
        super();
        this.left = left;
        this.right = right;
    }

    //-----------------------------------------------------------------------
    /**
     * {@inheritDoc}
     */
    @Override
    public L getLeft() {
        return left;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public R getRight() {
        return right;
    }

    /**
     * <p>Throws {@code UnsupportedOperationException}.</p>
     *
     * <p>This pair is immutable, so this operation is not supported.</p>
     *
     * @param value  the value to set
     * @return never
     * @throws UnsupportedOperationException as this operation is not supported
     */
    @Override
    public R setValue(final R value) {
        throw new UnsupportedOperationException();
    }

}

public final L left;public final R right;兩個(gè)不可變的值注定了這個(gè)類是不可變的瀑梗。
在構(gòu)造方法ImmutablePair(final L left, final R right)中初始化這兩個(gè)值。
本類實(shí)現(xiàn)了 getLeft()getRight()方法裳扯,返回leftright抛丽。
當(dāng)我們?cè)噲D調(diào)用setValue()方法的時(shí)候會(huì)拋出UnsupportedOperationException異常,因?yàn)檫@一對(duì)值是不可變的饰豺。

ImmutablePair.class

 public void setRight(final R right) {
        this.right = right;
    }
public void setLeft(final L left) {
    this.left = left;
}
public R setValue(final R value) {
        final R result = getRight();
        setRight(value);
        return result;
    }

MutablePairImmutablePair類基本一樣亿鲜,只是在定義public L left;public R right;沒(méi)有使用final類型的。注定了可以修改這兩個(gè)值冤吨。并且提供了setter方法可以供修改這一對(duì)值蒿柳,并且提供了setValuef()方法修改right值。

現(xiàn)在我們可以愉快的使用這個(gè)類來(lái)作為返回兩個(gè)參數(shù)的方法的返回值了漩蟆。

提問(wèn)

如果你想問(wèn)垒探,我返回的參數(shù)不是2個(gè),是3個(gè)怎么辦怠李?

沒(méi)問(wèn)題叛复,一樣滿足你,在這個(gè)org.apache.commons.lang3.tuple包中提供了針對(duì)構(gòu)建三個(gè)元素的Triple類扔仓,類定義中abstract class Triple<L, M, R>褐奥。定義了3個(gè)泛型同樣提供了ImmutableTripleMutableTriple一對(duì)不可變和可變的實(shí)現(xiàn)類。

你過(guò)你還問(wèn)我翘簇,我返回的參數(shù)是4個(gè)怎么辦撬码,還有什么類可以供我使用嗎?

抱歉版保,或許你需要定義java bean 去實(shí)現(xiàn)你的復(fù)雜返回值:)呜笑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夫否,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子叫胁,更是在濱河造成了極大的恐慌凰慈,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驼鹅,死亡現(xiàn)場(chǎng)離奇詭異微谓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)输钩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門豺型,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人买乃,你說(shuō)我怎么就攤上這事姻氨。” “怎么了剪验?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵肴焊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我功戚,道長(zhǎng)抖韩,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任疫铜,我火速辦了婚禮茂浮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壳咕。我一直安慰自己席揽,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布谓厘。 她就那樣靜靜地躺著幌羞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竟稳。 梳的紋絲不亂的頭發(fā)上属桦,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音他爸,去河邊找鬼聂宾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诊笤,可吹牛的內(nèi)容都是我干的系谐。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纪他!你這毒婦竟也來(lái)了鄙煤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茶袒,失蹤者是張志新(化名)和其女友劉穎梯刚,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體薪寓,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亡资,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了预愤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沟于。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咳胃,死狀恐怖植康,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情展懈,我是刑警寧澤销睁,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站存崖,受9級(jí)特大地震影響冻记,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜来惧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一冗栗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧供搀,春花似錦隅居、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至屿脐,卻和暖如春涕蚤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背的诵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工万栅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人西疤。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓申钩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親瘪阁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子撒遣,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容