集合
Collection
List
- 有序,有下标,元素可以重复
实现类
- ArrayList
数组结构实现,查询快,增删慢(必须开辟连续的空间)
jdk1.2版本,运行效率快,线程不安全
- Vector
数组结构实现,查询快,增删慢
jdk1.0版本,运行效率慢,线程安全
- LinkedList
链表结构实现,查询慢,增删快(无需开辟连续的空间)
jdk1.2版本,运行效率快,线程不安全
为什么ArrayList查询效率高,删除效率慢
ArrayLIst查询效率高:ArrayLIst是连续存放元素的,找到第一个元素的首地址,再加上每个元素的占据的字节大小就能定位到对应的元素。
LinkedList插入删除效率高。因为执行插入删除操作时,只需要操作引用即可,元素不需要移动元素,他们分布在内存的不同地方,通过引用来互相关联起来。而ArrayLIst需要移动元素,故效率低。
ArrayList
没有向集合添加任何元素的时候,容量为0, 第一次add数据的时候,初始容量就是10,然后按照1.5倍扩容(10->15->22->…)
遍历(迭代器)
ListIterator
- 迭代器可以从前往后,也可以从后往前
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
ListIterator<Integer> integerListIterator = list.listIterator();
System.out.println("ListIterator从前往后遍历---》");
while (integerListIterator.hasNext()) {
System.out.println(integerListIterator.nextIndex()+"======="+integerListIterator.next());
}
System.out.println("ListIterator从后往前遍历---》");
while (integerListIterator.hasPrevious()) {
System.out.println(integerListIterator.previousIndex()+"======="+integerListIterator.previous());
}
}
输出
ListIterator从前往后遍历---》
0=======10
1=======20
2=======30
3=======40
4=======50
5=======60
ListIterator从后往前遍历---》
5=======60
4=======50
3=======40
2=======30
1=======20
0=======10
基本类型,自助装箱
subList
- 返回子集合
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
list.add(60);
List<Integer> subList = list.subList(0, 3);
//下面打印 [10, 20, 30]
System.out.println(subList.toString());
}
remove
源码
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
//这里比较的是地址,所以删除对象的时候,只比较值的话,需要重写equal和hashCode
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
public boolean equals(Object obj) {
return (this == obj);
}
重写Student后,就可以通过对象删除了 list.remove(new Student(“张三”, 3));
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (o instanceof Student) {
Student student = (Student) o;
return this.age == student.age && Objects.equals(this.name, student.name);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
Student s1 = new Student("张三", 3);
Student s2 = new Student("李四", 4);
Student s3 = new Student("王五", 5);
list.add(s1);
list.add(s2);
list.add(s3);
System.out.println(list.toString());
//删除
list.remove(new Student("张三", 3));
System.out.println("删除后(已经重写了Student的equal和hashCode)" + list.toString());
}
输出
[Student{name='张三', age=3}, Student{name='李四', age=4}, Student{name='王五', age=5}]
删除后(已经重写了Student的equal和hashCode)[Student{name='李四', age=4}, Student{name='王五', age=5}]
ArrayList部分源码
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//默认初始容量
private static final int DEFAULT_CAPACITY = 10;
//实际元素的大小
private int size;
//存放元素的数组
transient Object[] elementData;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//没有向集合添加任何元素的时候,容量为0, 第一次add数据的时候,初始容量就是10,然后按照1.5倍扩容(10->15->22->...)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
*核心代码
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
Vector
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
vector.add("C");
vector.add("D");
vector.add("E");
System.out.println(vector);
//遍历1
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + "\t");
}
System.out.println();
//遍历2 枚举器
Enumeration<String> elements = vector.elements();
while (elements.hasMoreElements()) {
System.out.print(elements.nextElement() + "\t");
}
}
LinkedList
双向链表
public static void main(String[] args) {
LinkedList<Student> linkedList = new LinkedList<>();
Student s1 = new Student("张三",3);
Student s2 = new Student("李四",4);
Student s3 = new Student("王五",5);
Student s4 = new Student("赵流六",6);
linkedList.add(s1);
linkedList.add(s2);
linkedList.add(s3);
linkedList.add(s4);
System.out.println(linkedList);
System.out.println("=====遍历:增强型for循环=======");
for (Student student : linkedList) {
System.out.println(student.toString());
}
System.out.println("=====遍历:迭代器=======");
Iterator<Student> iterator = linkedList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
源码
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
//实际元素的大小
transient int size = 0;
//链表头节点
transient Node<E> first;
//链表尾节点
transient Node<E> last;
//修改次数
protected transient int modCount = 0;
/**
* 空参数的构造由于生成一个空链表 first = last = null
*/
public LinkedList() {
}
public boolean add(E e) {
linkLast(e);
return true;
}
/**
*核心代码
*/
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);//当前节点的prev指向了上一个节点,第一次添加的时候prev节点为null
last = newNode;//链表尾节点last指向当前节点
if (l == null)
first = newNode;//第一次添加的时候,头节点first指向了当前添加的节点
else
l.next = newNode;//上个节点的next指向了当前节点
size++;
modCount++;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}
Set
- 特点:无序,无下标,元素不可以重复
HashSet
- 存储接口:哈希表(数据+链表(单向链表)+红黑树)
- 存储过程
- 根据hashCode,计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
- 再执行equals方法,如果equals方法为true,则认为是重复,否则,形成链表
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(3);
set.add(4);
set.add(1);
set.add(2);
System.out.println(set);
System.out.println("====遍历====");
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
重写hashCode和equal
源码分析
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
//HashSet实际使用HashMap的key储存元素的,value = new Object()
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
}
TreeSet
- 基于排列顺序实现元素不重复
- 实现了SortedSet接口,对集合元素自动排序
- 元素对象的类型必须实现Comparable,指定排序规则
- 通过compareTo方法确定是否为重复元素
- 存储结构:红黑树
public class NewStudent implements Comparable<NewStudent> {
private String name;
private int age;
public NewStudent(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "NewStudent{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(NewStudent o) {
int i = this.name.compareTo(o.name);
int j = this.age - o.age;
return i == 0 ? j : i;
}
}
验证
public static void main(String[] args) {
TreeSet<NewStudent> treeSet = new TreeSet<>();
NewStudent s1 = new NewStudent("zhangsan",13);
NewStudent s2 = new NewStudent("lisi",14);
NewStudent s3 = new NewStudent("wangwu",15);
NewStudent s4 = new NewStudent("zhaoliu",18);
NewStudent s5 = new NewStudent("zhaoliu",17);
//重复,添加不了
// NewStudent s6 = new NewStudent("zhaoliu",17);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
// treeSet.add(s6);
System.out.println(treeSet.size());
System.out.println(treeSet);
}
Comparator接口
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2) {
int i = o1.getName().compareTo(o2.getName());
int j = o1.getAge() - o2.getAge();
return i == 0 ? j : i;
}
});
//也可以简化一下,用lambda表达式
/*TreeSet<Student> treeSet = new TreeSet<>((o1, o2) -> {
int i = o1.getName().compareTo(o2.getName());
int j = o1.getAge() - o2.getAge();
return i == 0 ? j : i;
});*/
Student s1 = new Student("zhangsan",13);
Student s2 = new Student("lisi",14);
Student s3 = new Student("wangwu",15);
Student s4 = new Student("zhaoliu",18);
Student s5 = new Student("zhaoliu",17);
//重复,添加不了
// NewStudent s6 = new NewStudent("zhaoliu",17);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
// treeSet.add(s6);
System.out.println(treeSet.size());
System.out.println(treeSet);
}
源码
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable {
//java.util.NavigableMap 可以看api帮助文档
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
}
Map
- 无序
- 存储键值对
- 键不能重复,值可以重复
实现类
- HashMap
JDK1.2版本,线程不安全,运行效率快,允许null作为key或者value
- HashTable(很少用)
JDK1.0版本,线程安全,运行效率慢,不允许null作为key或者value
- Properties
HashTable的子类,要求key和value都是String。通常用于配置文件的读取
- TreeMap
实现了SortedMap接口,可以对key自动排序
HashMap
- 存储结构:哈希表(数组+链表+红黑树)
- 使用key的hashCode和equals作为重复依据
entrySet效率要高于keySet
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>(16);
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.put("D", 1);
map.put("E", 1);
map.put("F", 1);
map.put("G", 1);
map.put("H", 1);
System.out.println(map);
System.out.println("========entrySet=========");
Set<Map.Entry<String, Integer>> entries = map.entrySet();
long start = System.currentTimeMillis();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + "=======" + entry.getValue());
}
long end = System.currentTimeMillis();
System.out.println("entrySet用时:" + (end - start));
System.out.println("========keySet=========");
Set<String> strings = map.keySet();
for (String string : strings) {
System.out.println(string + "=======" + map.get(string));
}
long end2 = System.currentTimeMillis();
System.out.println("keySet用时:" + (end2 - end));
}
源码
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
//默认初始容量 16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认的加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//树化阀值
static final int TREEIFY_THRESHOLD = 8;
//树还原链表阀值 当链表长度小于6的时候,红黑树会还原为链表
static final int UNTREEIFY_THRESHOLD = 6;
//最小树化容量 jdk1.8 当链表长度大于8 并且数组元素个数>=64,链表会转化为红黑树
static final int MIN_TREEIFY_CAPACITY = 64;
//数组+链表(单向链表,next)
transient Node<K,V>[] table;
//键值对的数量
transient int size;
//加载因子
final float loadFactor;
//下一次扩容的阀值
int threshold;
//节点(键值对),单向链表
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
//...
}
}
无参构造方法
public HashMap() {
//加载因子为默认加载因子0.75f
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
有参构造方法
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public HashMap(int initialCapacity, float loadFactor) {
//校验传入的容量
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
//传入的容量大于最大容量,就等于最大容量(2的30次方)
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
//校验加载因子
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
put
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//计算key的hash值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//put值
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
总结
- HashMap刚刚创建时,table是null,为了节省空间,当添加第一个元素时,table容量调整为16
- 当元素个数大于阀值(16*0.75=12)时,会进行扩容,扩容后大小为原来的2倍。目的是减少调整元素的个数
- jdk1.8 当单个链表长度大于8,并且数组元素个数大于等于64时,会调整为红黑树,目的提高执行效率
- jdk1.8 当链表长度小于6时,调整为链表
- jdk1.8以前,链表是头插入,jdk1.8以后是尾插入
TreeMap
- 存储结构:红黑树
public class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (o instanceof Student) {
Student student = (Student) o;
return this.age == student.age && Objects.equals(this.name, student.name);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public int compareTo(Student o) {
int i = this.name.compareTo(o.name);
int j = this.age - o.age;
return i == 0 ? j : i;
}
}
测试类
public static void main(String[] args) {
Map<Student, String> map = new TreeMap<>();
//或者自定义比较器
/*Map<Student, String> map = new TreeMap<>((o1, o2) -> {
int i = o1.getName().compareTo(o2.getName());
int j = o1.getAge() - o2.getAge();
return i == 0 ? j : i;
});*/
Student s1 = new Student("zhangsan", 12);
Student s2 = new Student("lisi", 18);
Student s3 = new Student("wangwu", 20);
Student s4 = new Student("zhaoliu", 8);
map.put(s1, "北京");
map.put(s2, "南京");
map.put(s3, "天津");
map.put(s4, "深圳");
// map.put(new Student("zhaoliu", 8), "广州");
System.out.println(map.size());
System.out.println(map);
}
源码
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable {
//比较器
private final Comparator<? super K> comparator;
//根节点
private transient Entry<K,V> root;
//键值对数量
private transient int size = 0;
//修改次数
private transient int modCount = 0;
//无参构造方法
public TreeMap() {
comparator = null;
}
//有参构造方法,自定义比较器
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;
}
//put方法
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
}
泛型
- 泛型类
- 泛型接口
- 泛型方法
泛型类
public class GenericDemo<T> {
/**
* 泛型成员变量
*/
private T t;
/**
* 泛型返回值
*
* @return
*/
public T getT() {
return t;
}
/**
* 泛型形参
*
* @param t
*/
public void setT(T t) {
this.t = t;
}
}
泛型接口
public interface GenericInterfaceDemo<T> {
T get(T t);
}
实现接口的时候指定泛型
public class GenericInterfaceImplDemo implements GenericInterfaceDemo<String> {
@Override
public String get(String s) {
return s;
}
}
让实例化对象的时候指定泛型
public class GenericInterfaceImplDemo2<T> implements GenericInterfaceDemo<T> {
@Override
public T get(T t) {
return t;
}
}
验证
public static void main(String[] args) {
GenericInterfaceImplDemo genericInterfaceImplDemo = new GenericInterfaceImplDemo();
System.out.println(genericInterfaceImplDemo.get("dsd"));
GenericInterfaceImplDemo2<Integer> genericInterfaceImplDemo2 = new GenericInterfaceImplDemo2();
System.out.println(genericInterfaceImplDemo2.get(123));
//下面是验证泛型方法
GenericMethodDemo demo = new GenericMethodDemo();
Student s1 = new Student("张三", 3);
System.out.println(demo.get(s1));
}
泛型方法
public class GenericMethodDemo {
/**
* 语法:<T> 方法返回值 就是在方法的返回值之前加上<T>
* @param t
* @param <T>
* @return
*/
public <T> T get(T t) {
return t;
}
}
Collections工具类
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(13);
list.add(50);
list.add(1);
list.add(3);
list.add(10);
list.add(8);
System.out.println("原集合"+list);
Collections.sort(list);
System.out.println("排序后"+list);
System.out.println("二分查找"+Collections.binarySearch(list, 13));
List desList = new ArrayList();
//这里不能忽略,不然复制失败
for (Integer integer : list) {
desList.add(0);
}
Collections.copy(desList, list);
System.out.println("复制数组"+desList);
Collections.reverse(list);
System.out.println("反转"+list);
Collections.shuffle(list);
System.out.println("打乱"+list);
//补充,list转数组
System.out.println("====list转数组======");
Integer[] integers = list.toArray(new Integer[list.size()]);
System.out.println(integers.length);
System.out.println(Arrays.toString(integers));
//数组转list
System.out.println("====数组转list======");
//基本数据类型数组转成集合是,需要修改为包装类
Integer[] ints = {0,9,4,2,1,8};
List<Integer> numberList = Arrays.asList(ints);
//集合是一个受限集合,不能添加和删除
//numberList.add(3);
//numberList.remove(0);
System.out.println(numberList);
}