import java.util.Set;
import java.util.HashSet;
import java.util.Collection;
import java.util.Comparator;

public class Search {

   public static boolean search (int v, int[] data) {
      for (int x: data) if (x==v) return true;
      return false;
   }

   public static boolean search (int v, int[] data, int first, int n) {
      for (int i=first; i<n; i++) if (data[i]==v) return true;
      return false;
   }

   public static boolean searchI (int v, Collection<Integer> data) {
      // NB. Both x and v are of type 'int', not 'Integer'.
      for (int x: data) if (x==v) return true;
      return false;
   }

   public static boolean searchII (Integer v, Collection<Integer> data) {
      // If numeric types, then auto-unboxing conversions apply to ==,
      // and the RHS is unboxed
      for (int x: data) if (x==v) return true;
      return false;
   }

   public static boolean searchIII (Integer v, Collection<Integer> data) {
      // NB.  Dangerous reference equality is used here!
      for (Integer x: data) if (x==v) return true;
      return false;
   }

   public static <T> boolean gsearch (T v, Collection<T> data) {
      for (T x: data) if (x.equals(v)) return true;
      return false;
   }

   // Pretty much forces T to implement Comparable<T>
   public static <T> boolean gsearchZ (Comparable<T> v, Collection<T> data) {
      for (T x: data) if (v.compareTo(x)==0) return true;
      return false;
   }

   // Subtype constraint; T must have a natural ordering
   public static <T extends Comparable<T>> boolean gsearch (T v, Collection<T> data) {
      for (T x: data) if (v.compareTo(x)==0) return true;
      return false;
   }

   // External means of comparision 
   public static <T> boolean gsearch (T v, Collection<T> data, Comparator<T> comp) {
      for (T x: data) if (comp.compare(x,v)==0) return true;
      return false;
   }

   public static void main (final String [] args) {
      final int [] data  = new int [args.length];
      final Set<Integer> set = new HashSet<>();
      final int v = Integer.parseInt (args[0]);
      int n = 0;
      for (int i=1; i<args.length; i++) {
         try {
            final int k = Integer.parseInt (args[i]);
            data[n++] = k;
            set.add (k);
         } catch (NumberFormatException ex) {
            ex.printStackTrace (System.err);
         }
      }

      boolean f = search (v, data);
      System.out.printf ("%d %sfound%n", v, f?"":"not ");
      f = searchI (v, set);
      System.out.printf ("%d %sfound%n", v, f?"":"not ");
      f = searchII (v, set);
      System.out.printf ("%d %sfound%n", v, f?"":"not ");
      f = searchIII (v, set);
      System.out.printf ("%d %sfound%n", v, f?"":"not ");
      f = gsearch (v, set);
      System.out.printf ("%d %sfound%n", v, f?"":"not ");

      System.out.printf ("%b%n", new Integer(4).equals(new Integer(4)));
      System.out.printf ("%b%n", new Integer(40000).equals(new Integer(40000)));

      //  Both are reference types, so reference equality is used; hence "false"
      System.out.printf ("%b%n", new Integer(4) == new Integer(4));
      System.out.printf ("%b%n", new Integer(40000) == new Integer(40000));
   }
}