配列、リストの要素が全て同じかチェックする

Java8 でも動くことを前提にする。(まだ Java8 を使う企業が多いからだ)

配列
equals で比較できる場合

public static <T> boolean matchElements(T[] ary) {
   if (ary.length < 2) return true;
   for(int i=0, j=1; j < ary.length; i++, j++) {
      if (!ary[i].equals(ary[j])) return false;
   }
   return true;
}

比較を BiPredicate にすることで equals と違う方法で判定する

public static <T> boolean matchElements(T[] ary, BiPredicate<T, T> m) {
   if (ary.length < 2) return true;
   for(int i=0, j=1; j < ary.length; i++, j++) {
      if (!m.test(ary[i], ary[j])) return false;
   }
   return true;
}

null がある場合、↑の BiPredicate を記述する中で対処すれば良いのだが、
あえて null の場合に BiPredicate に渡すものを定義するなら、

public static <T> boolean matchElements(T[] ary, BiPredicate<T, T> m, Supplier<T> nsup) {
   if (ary.length < 2) return true;
   for(int i=0, j=1; j < ary.length; i++, j++) {
      if (!m.test(Optional.ofNullable(ary[i]).orElse(nsup.get())
            , Optional.ofNullable(ary[j]).orElse(nsup.get()))) return false;
   }
   return true;
}

List で、イテレータを使う場合、

public static <T> boolean matchElements(List<T> list, BiPredicate<T, T> p) {
   for(ListIterator<T> it = list.listIterator(); it.hasNext();){
      T t = it.next();
      if (it.hasPrevious()){
         T u = it.previous();
         if (it.hasPrevious()){
            u = it.previous();
            if (!p.test(u, t)) return false;
            it.next();
         }
         it.next();
      }
   }
   return true;
}

null の場合に BiPredicate に渡すものを定義するなら、

public static <T> boolean matchElements(List<T> list, BiPredicate<T, T> p, Supplier<T> nsup) {
   for(ListIterator<T> it = list.listIterator(); it.hasNext();){
      T t = it.next();
      if (it.hasPrevious()){
         T u = it.previous();
         if (it.hasPrevious()){
            u = it.previous();
            if (!p.test(Optional.ofNullable(u).orElse(nsup.get())
                  , Optional.ofNullable(t).orElse(nsup.get()))) return false;
            it.next();
         }
         it.next();
      }
   }
   return true;
}


Stream で処理、
Collectors.groupingBy でカウントして調べる

public static <T, K> boolean matchElements(Collection<T> c, Function<T, K> m) {
   return c.stream().collect(Collectors.groupingBy(t->m.apply(t), Collectors.counting())).size()==1;
}

但し、これはFunction が null を返してはならない。

要素が null の場合を考慮していないので、null を除くなら

public static <T, K> boolean matchElements(Collection<T> c, Function<T, K> m) {
   return c.stream().filter(t->t != null)
      .collect(Collectors.groupingBy(t->m.apply(t), Collectors.counting())).size()==1;
}

そもそも、null の場合、別の値に置き換えて Function を実行させれば、Function の記述も楽になる。

public static <T, K> boolean matchElements(Collection<T> c, Function<T, K> m, Supplier<T> nullTemp) {
   return c.stream().map(t->Optional.ofNullable(t).orElse(nullTemp.get()))
      .collect(Collectors.groupingBy(t->m.apply(t), Collectors.counting())).size()==1;
}