泛型的理解
泛型类
class 类名 <泛型类型1,泛型类型2,…>{
}
泛型方法
修饰符 <泛型类型1,泛型类型2, …> 返回值 方法名 (形参列表){
}
泛型接口
interface 接口名 <泛型类型1,泛型类型2, …>{
}
泛型接口的使用
①使用接口的类不是泛型类
class 实现类类名 implements 接口名<具体类型>{
}
②使用接口的类是泛型类
class 实现类类名 <泛型标识符1> implements 接口名<泛型标识符1>{
}
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.Collection;
public class 静态方法和非静态方法泛型的区别 <T,E> { //再类中声明泛型
//main方法是静态方法,并且在main方法上没有声明泛型,所以<报错>,
//但是<String>不报错,我理解为<String>就算是声明泛型并且确定了泛型的类型.
public static void main(String[] args) {
Collection<T> c1 = new ArrayList();
Collection<String> c2 = new ArrayList();
}
//静态方法必须在定义方法的时候重新声明泛型,在方法体中才能使用.
public static <T> void a() { //在方法上声明泛型
ArrayList<T> al1 = new ArrayList();
Collection<String> c1 = new ArrayList();
}
//非静态方法,方法体中可以使用所在类上的泛型
public void b() {
Collection<E> c1 = new ArrayList();
ArrayList<E> al1 = new ArrayList();
}
}
集合和数组的区别
- 数组既可以储存基本数据类型也可以储存引用数据类型,集合只能储存引用数据类型,但当集合储存基本数据类型时会自动进行装箱操作.
- 数组的长度不能改变,集合可以任意改变.
集合的体系结构
集合中部分常用的接口和类:
Collection接口
Collection是单列集合的根接口.接口不能实例化,所以只能使用Collection类型的引用指向它的实现类对象.(多态)
例如:
ArrayList是Collection一个实现类.
Collection c = new ArrayList();
Collection的遍历方式
第一种遍历
把集合转为数组,然后遍历数组:
- Object[] toArray(); 返回该集合中所有元素的数组,返回数组类型为Object.
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_遍历一 {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("哈哈1");
c.add(100);
c.add(3.14);
c.add('a');
c.add("哈哈2");
//使用toArray()方法把c转为Object类型的数组arr
Object[] arr = c.toArray();
//使用for循环遍历arr数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//使用增强for循环遍历arr数组
for (Object o : arr) {
System.out.println(o);
}
}
}
- Object[] toArray(); 返回该集合中所有元素的数组,返回数组类型为Object.
1.参数数组的长度, 小于Set集合元素的个数, 在toArray()就会返回一个该类的新数组. 2.参数数组的长度, 等于Set集合元素的个数, 方法内部就不在创建新数组了, 返回的数组就是传入的数组, 数组中装的就是集合中的元素 3.参数数组的长度, 大于Set集合元素的个数, 方法内部就不在创建新数组了,返回的数组就是传入的数组, 只会把Set集合从前向后向这个数组中存储. 多余空间就是默认值null.
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.Collection;
public class Collection_遍历一 {
public static void main(String[] args) {
Collection<String> c = new ArrayList();
c.add("哈哈1");
c.add("哈哈2");
c.add("哈哈3");
c.add("哈哈4");
c.add("哈哈5");
//使用toArray(T[] t)方法把c转为String类型的数组arr
String[] arr = c.toArray(new String[0]);
//使用for循环遍历arr数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
//使用增强for循环遍历arr数组
for (String o : arr) {
System.out.println(o);
}
}
}
第二种遍历
迭代器:iterator.调用方法iterator()方法获取一个迭代器对象.
Itrator it = Collection对象.iterator();
hashNext();判断迭代器当前位置的下一位置还有没有元素.
next();返回下一个元素.
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Collection_遍历二 <T>{
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(1);
c.add(3.14);
c.add("aaa");
printCollection(c);
}
public static <T> void printCollection(Collection<T> c) {
//创建迭代器
Iterator<T> it = c.iterator();
//使用.hasNext();方法判断是否还有下一个元素
while(it.hasNext()) {
//获取下一个元素,
T next = it.next();
System.out.println(next);
//看看每个元素的运行时类
System.out.println(next.getClass());
}
}
}
List
List是Collection一个子接口.其储存特点:有序,有索引(下标),元素可以重复.
和Collection一样List只能使用List类型的引用指向它的实现类对象.
List l = new ArrayList();
List的第三种遍历方式
不需要转换位数组:使用for循环,循环次数为size(),元素获取get(int index);
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.List;
public class List的第三种遍历方式 {
public static void main(String[] args) {
List l1 = new ArrayList();
l1.add("赵新");
l1.add(521);
l1.add(3.14);
l1.add(1, "我爱你");
for (int i = 0; i < l1.size(); i++) {
Object o = l1.get(i);
System.out.println(o);
}
}
}
vector
顺序存储, 底层是数组实现, 查改块,增删慢.特有方法如下:
1.addElement(Object e) 添加元素
2.removeElement(Object e) 删除元素
特有的遍历方式
Enumeration 枚举器类型
获取枚举器的方式: elements()
枚举器常用方法:
hasMoreElements(): 判断是否有下一个元素 跟迭代器的hasNext功能一样.
nextElement(): 取出下一个元素 跟迭代器的next功能一样
package com.ujiuye.vector;
import java.util.Enumeration;
import java.util.Vector;
public class Vector类 {
public static void main(String[] args) {
Vector v = new Vector();
v.addElement("吴春波");
v.addElement("田馨方");
v.addElement("郭祥");
v.addElement("谢进");
// System.out.println(v);
// v.removeElement("郭祥");
// System.out.println(v);
// 使用枚举器
Enumeration en = v.elements();
while(en.hasMoreElements()) {
Object o = en.nextElement();
System.out.println(o);
}
}
}
ArrayList类
ArrayList是List的实现类.
1.多线程不安全, 效率高
2.顺序存储, 数组实现, 查改块, 增删慢
采用的是顺序存储
遍历
package com.youjiuye.prictice;
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayList练习 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("你的");
al.add("益达");
al.add("丢了");
//可以添加重复元素
al.add("益达");
//第一种遍历方式
for (int i = 0; i < al.size(); i++) {
String s = al.get(i);
System.out.println(s);
}
//第二种遍历方式
String[] arr = new String[0];
arr = al.toArray(arr);
for (int j = 0; j < arr.length; j++) {
System.out.println(arr[j]);
}
//第三种遍历方式
Iterator<String> it = al.iterator();
while(it.hasNext()) {
String next = it.next();
System.out.println(next);
}
}
}
LinkedList
LinkedList是List接口的实现类
- 节点实现,链式存储.查改慢, 增删快
- 每一个元素都存储在一个节点中, 节点中出了存储元素本身, 还会存储逻辑相邻的下一个元素的地址.
Set
特点:
- Set是Collection的一个子接口
- 无序: 元素添加后存储不是按照添加的顺序存储的,存储的顺序和取出的顺序不一致;
- 没有索引: 在Set集合中无法通过下标去区分元素.
- 唯一(不能重复): 相同的元素Set集合只能保存一份.
由于接口不能实例化 所以只能使用Set类型的引用指向它的实现类对象:
Set s = new HashSet<>();
Hashset
HashSet存储元素的步骤 :
- 某个对象,在即将存储到HashSet的时候, 先获取该对象哈希值.
- 哈希值对初始容量取余, 余数是几,就应该放在哈希表的那一列下.
- 使用该元素哈希值,与这一列下的所有元素哈希值比较, 如果哈希值都不一样, 就直接添加,如果发现和若干个已添加元素哈希值一样.
- 比较要添加元素和若干个哈希值一样的equals方法, 如果所有equals比较结果都返回false, 就添加;如果有一个equals返回true,就不添加.
存储过程简略图 :
自定义类型在HashSet中如何保证元素唯一性
1.重写hashCode方法
1.相同对象, 一定要有相同哈希值
2.不同对象, 尽量要有不同的哈希值, 为了提高哈希表存储效率.
3.重写hashCode围绕了对象属性重写的.
2.重写equals方法
不仅仅比较地址, 还要比较类型, 还要比较属性值.
3.重写hashCode和equals的方式:
alt+shift+s --> h
LinkedHashSet类
1.LinkedHashSet是HashSet的子类, 和HashSet一样存储元素能保证元素的唯一.
2.LinkedHashSet底层的实现和HashSet不一样,LinkedHashSet底层使用时哈希表+链表的方式.链表可以用来维护元素的存储顺序,
哈希表用来保证元素的唯一性.
3.LinkedHashSet存储特点: 有序且唯一. 元素的添加的顺序和元素取出的顺序一致.具有可预知的迭代性.
4.LinkedHashSet的使用场景: 当你要存储的元素需要唯一且有序的时使用它的.
Map
Map是双列集合的顶层接口.Map集合的特点:
1.key值: 在Map唯一,不能重复.
2.value值: 在Map不要唯一, 可以重复, 多个key值可以对应同一个value值;
3.key和value之间的关系: 键值对的关系
4.每一个key值只对应一个value值.
Map集合的第一种遍历方式
keyset(); 返回一个set集合,储存所有key值.
get(Object key); 取出Kap集合的value值.
package com.youjiuye.class1;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Map遍历一 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("赵新", 24);
map.put("周冬雨", 25);
//遍历
Set<String> ks = map.keySet();
//for
for (String key : ks) {
Integer value = map.get(key);
System.out.println(key+"-->"+value);
}
//迭代器
Iterator<String> it = ks.iterator();
while (it.hasNext()) {
String key = it.next();
Integer value = map.get(key);
System.out.println(key+"-->"+value);
}
}
}
Map集合的第二种遍历方式
map.entrySet(); 获取存储键值对对象Set集合.
getKey(); 获取Ket值.
getvalue(); 获取value值.
package com.youjiuye.class1;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Map遍历二 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("赵新", 24);
map.put("周冬雨", 25);
Set<Entry<String, Integer>> set_entry = map.entrySet();
for (Entry<String, Integer> en : set_entry) {
String key = en.getKey();
Integer value = en.getValue();
System.out.println(key + "-->" + value);
}
}
}
HashMap
Map的实现类.
需要重写hashcode和equals.
LinkedHashMap类
LinkedHashMap是HashMap的一个子类.它的底层实现哈希表+链表的方法, 所以它存储的键值对的特点: 是有序且唯一. 键值对添加顺序和取出的顺序一致.
Collections工具类
package com.ujiuye.collections;
import java.util.ArrayList;
import java.util.Collections;
public class Collections工具类 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(10);
list.add(5);
list.add(3);
list.add(8);
list.add(10);
list.add(10);
System.out.println(list);
// 1. 排序
Collections.sort(list);
System.out.println(list);
// 2.二分查找
int i = Collections.binarySearch(list, 4);
System.out.println(i);
// 3. 反转
Collections.reverse(list);
System.out.println(list);
// 4.填充
/*Collections.fill(list, 5);
System.out.println(list);*/
// 5. 最大
Integer max = Collections.max(list);
System.out.println(max);
// 6. 最小
Integer min = Collections.min(list);
System.out.println(min);
// 7. 随机打乱集合中元素
Collections.shuffle(list);
System.out.println(list);
// 8. 交换元素顺序
Collections.swap(list, 0, 1);
System.out.println(list);
// 9. 获取元素个数
int j = Collections.frequency(list, 10);
System.out.println(j);
// 10. 替换
Collections.replaceAll(list, 10, 66);
System.out.println(list);
}
}
练习:
斗地主(制牌-洗牌-发牌-看牌)