泛型
元组件,写几个DTO
// onjava/Tuple2.java package onjava; public class Tuple2<A, B> { public final A a1; public final B a2; public Tuple2(A a, B b) { a1 = a; a2 = b; } public String rep() { return a1 + ", " + a2; } @Override public String toString() { return "(" + rep() + ")"; } }
这里根本不需要get和private,因为final已经保证了不可变
// onjava/Tuple3.java package onjava; public class Tuple3<A, B, C> extends Tuple2<A, B> { public final C a3; public Tuple3(A a, B b, C c) { super(a, b); a3 = c; } @Override public String rep() { return super.rep() + ", " + a3; } } // onjava/Tuple4.java package onjava; public class Tuple4<A, B, C, D> extends Tuple3<A, B, C> { public final D a4; public Tuple4(A a, B b, C c, D d) { super(a, b, c); a4 = d; } @Override public String rep() { return super.rep() + ", " + a4; } } // onjava/Tuple5.java package onjava; public class Tuple5<A, B, C, D, E> extends Tuple4<A, B, C, D> { public final E a5; public Tuple5(A a, B b, C c, D d, E e) { super(a, b, c, d); a5 = e; } @Override public String rep() { return super.rep() + ", " + a5; } }
泛型Node的栈
// generics/LinkedStack.java // 用链式结构实现的堆栈 public class LinkedStack<T> { private static class Node<U> { U item; Node<U> next; Node() { item = null; next = null; } Node(U item, Node<U> next) { this.item = item; this.next = next; } boolean end() { return item == null && next == null; } } private Node<T> top = new Node<>(); // 栈顶 public void push(T item) { top = new Node<>(item, top); } public T pop() { T result = top.item; if (!top.end()) { top = top.next; } return result; } public static void main(String[] args) { LinkedStack<String> lss = new LinkedStack<>(); for (String s : "Phasers on stun!".split(" ")) { lss.push(s); } String s; while ((s = lss.pop()) != null) { System.out.println(s); } } }
RandomList
// generics/RandomList.java import java.util.*; import java.util.stream.*; public class RandomList<T> extends ArrayList<T> { private Random rand = new Random(47); public T select() { return get(rand.nextInt(size())); } public static void main(String[] args) { RandomList<String> rs = new RandomList<>(); Array.stream("The quick brown fox jumped over the lazy brown dog".split(" ")).forEach(rs::add); IntStream.range(0, 11).forEach(i -> System.out.print(rs.select() + " ")); ); } }
输出
brown over fox quick quick dog brown The brown lazy brown
一个实现Supplier<T>接口的例子
// generics/Fibonacci.java // Generate a Fibonacci sequence import java.util.function.*; import java.util.stream.*; public class Fibonacci implements Supplier<Integer> { private int count = 0; @Override public Integer get() { return fib(count++); } private int fib(int n) { if(n < 2) return 1; return fib(n-2) + fib(n-1); } public static void main(String[] args) { Stream.generate(new Fibonacci()) .limit(18) .map(n -> n + " ") .forEach(System.out::print); } }
我们不能直接对这么底层的代码调用,用一个适配器
// generics/IterableFibonacci.java // Adapt the Fibonacci class to make it Iterable import java.util.*; public class IterableFibonacci extends Fibonacci implements Iterable<Integer> { private int n; public IterableFibonacci(int count) { n = count; } @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { @Override public boolean hasNext() { return n > 0; } @Override public Integer next() { n--; return IterableFibonacci.this.get(); } @Override public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } public static void main(String[] args) { for(int i : new IterableFibonacci(18)) System.out.print(i + " "); } }
因为我们用foreach就说明用了迭代,我们需要手动控制一下迭代方式
泛型方法
如果方法是 static 的,则无法访问该类的泛型类型参数,因此,如果使用了泛型类型参数,则它必须是泛型方法。
要定义泛型方法,请将泛型参数列表放置在返回值之前,如下所示:
// generics/GenericMethods.java public class GenericMethods { public <T> void f(T x) { System.out.println(x.getClass().getName()); } public static void main(String[] args) { GenericMethods gm = new GenericMethods(); gm.f(""); gm.f(1); gm.f(1.0); gm.f(1.0F); gm.f('c'); gm.f(gm); } } /* Output: java.lang.String java.lang.Integer java.lang.Double java.lang.Float java.lang.Character GenericMethods */
变长参数和泛型方法
// generics/GenericVarargs.java import java.util.ArrayList; import java.util.List; public class GenericVarargs { @SafeVarargs public static <T> List<T> makeList(T... args) { List<T> result = new ArrayList<>(); for (T item : args) result.add(item); return result; } public static void main(String[] args) { List<String> ls = makeList("A"); System.out.println(ls); ls = makeList("A", "B", "C"); System.out.println(ls); ls = makeList( "ABCDEFFHIJKLMNOPQRSTUVWXYZ".split("")); System.out.println(ls); } } /* Output: [A] [A, B, C] [A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z] */
这里有个小细节,我们用static泛型方法的时候,如果下面这样
public class GenericVarargs<T> { @SafeVarargs public static List<T> makeList(T... args) { List<T> result = new ArrayList<>(); for (T item : args) result.add(item); return result; } }
【错误,因为static方法独立于类的初始化存在,所以在类上的泛型定义是不起作用的】
public class GenericVarargs<T> { @SafeVarargs public List<T> makeList(T... args) { List<T> result = new ArrayList<>(); for (T item : args) result.add(item); return result; } 【ok】
一个泛型化的Supplier
// onjava/BasicSupplier.java // Supplier from a class with a no-arg constructor package onjava; import java.util.function.Supplier; public class BasicSupplier<T> implements Supplier<T> { private Class<T> type; public BasicSupplier(Class<T> type) { this.type = type; } @Override public T get() { try { // Assumes type is a public class: return type.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); } } // Produce a default Supplier from a type token: public static <T> Supplier<T> create(Class<T> type) { return new BasicSupplier<>(type); } }
// generics/CountedObject.java public class CountedObject { private static long counter = 0; private final long id = counter++; public long id() { return id; } @Override public String toString() { return "CountedObject " + id; } }
// generics/BasicSupplierDemo.java import onjava.BasicSupplier; import java.util.stream.Stream; public class BasicSupplierDemo { public static void main(String[] args) { Stream.generate( BasicSupplier.create(CountedObject.class)) .limit(5) .forEach(System.out::println); } } /* Output: CountedObject 0 CountedObject 1 CountedObject 2 CountedObject 3 CountedObject 4 */
Sets
// onjava/Sets.java package onjava; import java.util.HashSet; import java.util.Set; public class Sets { public static <T> Set<T> union(Set<T> a, Set<T> b) { Set<T> result = new HashSet<>(a); result.addAll(b); return result; } public static <T> Set<T> intersection(Set<T> a, Set<T> b) { Set<T> result = new HashSet<>(a); result.retainAll(b); return result; } // Subtract subset from superset: public static <T> Set<T> difference(Set<T> superset, Set<T> subset) { Set<T> result = new HashSet<>(superset); result.removeAll(subset); return result; } // Reflexive--everything not in the intersection: public static <T> Set<T> complement(Set<T> a, Set<T> b) { return difference(union(a, b), intersection(a, b)); } }
前三个方法通过将第一个参数的引用复制到新的 HashSet 对象中来复制第一个参数,因此不会直接修改参数集合。因此,返回值是一个新的 Set 对象。
这四种方法代表数学集合操作: union()
返回一个包含两个参数并集的 Set , intersection()
返回一个包含两个参数集合交集的 Set , difference()
从 superset 中减去 subset 的元素 ,而 complement()
返回所有不在交集中的元素的 Set。
一个没有高级趣味的人。
email:hushui502@gmail.com