001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.commons.function;
018
019import static org.apache.juneau.commons.utils.Utils.*;
020
021import java.util.Optional;
022
023import org.apache.juneau.commons.lang.*;
024
025/**
026 * Represents an immutable tuple containing a single value.
027 *
028 * <p>
029 * This class provides a simple wrapper for a single value that properly implements
030 * {@link #equals(Object)} and {@link #hashCode()} based on content rather than identity.
031 * This is particularly useful for HashMap keys when you want to use an array or need
032 * a wrapper that uses content-based equality.
033 *
034 * <h5 class='section'>Features:</h5>
035 * <ul class='spaced-list'>
036 *    <li>Immutable - value cannot be changed after construction
037 *    <li>Content-based equality - uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for comparison
038 *    <li>Content-based hashing - uses {@link HashCode#of(Object...)} for hash code computation
039 *    <li>Array support - properly handles arrays with content-based equality and hashing
040 * </ul>
041 *
042 * <h5 class='section'>Array Support:</h5>
043 * <p>
044 * Unlike using arrays directly as HashMap keys (which use identity-based equality), this class properly
045 * handles arrays by using content-based equality and hashing via {@link HashCode#of(Object...)} which
046 * internally uses {@link java.util.Arrays#hashCode(Object[])} for arrays. This means two Tuple1 instances
047 * containing arrays with the same content will be considered equal.
048 *
049 * <h5 class='section'>Use Cases:</h5>
050 * <ul class='spaced-list'>
051 *    <li>Using arrays as HashMap keys with proper content-based equality
052 *    <li>Wrapping values that need content-based equality for collections
053 *    <li>Creating composite keys from single values
054 *    <li>Passing values through APIs that require object identity preservation
055 * </ul>
056 *
057 * <h5 class='section'>Usage:</h5>
058 * <p class='bjava'>
059 *    <jc>// Using arrays as keys via Tuple1</jc>
060 *    Map&lt;Tuple1&lt;String[]&gt;,Integer&gt; <jv>map</jv> = <jk>new</jk> HashMap&lt;&gt;();
061 *    <jv>map</jv>.put(Tuple1.<jsm>of</jsm>(<jk>new</jk> String[]{<js>"a"</js>,<js>"b"</js>}), 1);
062 *    <jv>map</jv>.put(Tuple1.<jsm>of</jsm>(<jk>new</jk> String[]{<js>"a"</js>,<js>"b"</js>}), 2);  <jc>// Replaces first entry</jc>
063 *    System.<jsf>out</jsf>.println(<jv>map</jv>.size());  <jc>// Prints "1"</jc>
064 *
065 *    <jc>// Using with other types</jc>
066 *    Map&lt;Tuple1&lt;String&gt;,Integer&gt; <jv>stringMap</jv> = <jk>new</jk> HashMap&lt;&gt;();
067 *    <jv>stringMap</jv>.put(Tuple1.<jsm>of</jsm>(<js>"key"</js>), 42);
068 *    Integer <jv>value</jv> = <jv>stringMap</jv>.get(Tuple1.<jsm>of</jsm>(<js>"key"</js>));  <jc>// Returns 42</jc>
069 * </p>
070 *
071 * <h5 class='section'>Thread Safety:</h5>
072 * <p>
073 * This class is immutable and therefore thread-safe. Multiple threads can safely access a Tuple1 instance
074 * concurrently without synchronization.
075 *
076 * <h5 class='section'>See Also:</h5><ul>
077 *    <li class='jc'>{@link Tuple2} - Two-value tuple
078 *    <li class='jc'>{@link Tuple3} - Three-value tuple
079 *    <li class='jc'>{@link Tuple4} - Four-value tuple
080 *    <li class='jc'>{@link Tuple5} - Five-value tuple
081 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsBasics">juneau-commons Basics</a>
082 * </ul>
083 *
084 * @param <A> The type of the value in this tuple.
085 */
086public class Tuple1<A> {
087
088   /**
089    * Creates a new tuple containing the specified value.
090    *
091    * <h5 class='section'>Example:</h5>
092    * <p class='bjava'>
093    *    Tuple1&lt;String&gt; <jv>tuple</jv> = Tuple1.<jsm>of</jsm>(<js>"value"</js>);
094    *    Tuple1&lt;String[]&gt; <jv>arrayTuple</jv> = Tuple1.<jsm>of</jsm>(<jk>new</jk> String[]{<js>"a"</js>, <js>"b"</js>});
095    * </p>
096    *
097    * @param <A> The value type.
098    * @param a The value to wrap in the tuple.
099    * @return A new tuple containing the specified value.
100    */
101   public static <A> Tuple1<A> of(A a) {
102      return new Tuple1<>(a);
103   }
104
105   private final A a;
106   private final int hashCode;
107
108   /**
109    * Constructor.
110    *
111    * @param a Object value.
112    */
113   public Tuple1(A a) {
114      this.a = a;
115      this.hashCode = h(a);
116   }
117
118   @Override /* Overridden from Object */
119   public boolean equals(Object o) {
120      return o instanceof Tuple1<?> o2 && eq(this, o2, (x, y) -> eq(x.a, y.a));
121   }
122
123   /**
124    * Returns the value contained in this tuple.
125    *
126    * <h5 class='section'>Example:</h5>
127    * <p class='bjava'>
128    *    Tuple1&lt;String&gt; <jv>tuple</jv> = Tuple1.<jsm>of</jsm>(<js>"hello"</js>);
129    *    String <jv>value</jv> = <jv>tuple</jv>.getA();  <jc>// Returns "hello"</jc>
130    * </p>
131    *
132    * @return The value contained in this tuple.
133    */
134   public A getA() { return a; }
135
136   /**
137    * Returns the value contained in this tuple wrapped in an {@link Optional}.
138    *
139    * <h5 class='section'>Example:</h5>
140    * <p class='bjava'>
141    *    Tuple1&lt;String&gt; <jv>tuple</jv> = Tuple1.<jsm>of</jsm>(<js>"hello"</js>);
142    *    Optional&lt;String&gt; <jv>value</jv> = <jv>tuple</jv>.optA();  <jc>// Returns Optional.of("hello")</jc>
143    *
144    *    Tuple1&lt;String&gt; <jv>tuple2</jv> = Tuple1.<jsm>of</jsm>(<jk>null</jk>);
145    *    Optional&lt;String&gt; <jv>value2</jv> = <jv>tuple2</jv>.optA();  <jc>// Returns Optional.empty()</jc>
146    * </p>
147    *
148    * @return The value wrapped in an Optional, or Optional.empty() if the value is null.
149    */
150   public Optional<A> optA() {
151      return Optional.ofNullable(a);
152   }
153
154   @Override /* Overridden from Object */
155   public int hashCode() {
156      return hashCode;
157   }
158}