Java高级学习-泛型
泛型
是一种未知的数据类型 (E) ,也可以看作是一个变量,用来接收数据类型。
E e : Element 元素
T t : Type 类型
创建集合对象的时候,就会确定泛型的数据类型。ArrayList
把数据类型作为参数传递,赋给泛型E。
创建集合对象不使用泛型,可以存储任意类型数据,不安全,可能会发生异常。
使用泛型好处:
避免类型转换麻烦将运行期异常,提升到编译器。
弊端:泛型是什么类型,只能存储什么类型的数据。
泛型的定义
不确定使用什么数据类型时,使用泛型。
泛型可以接受任意类型的数据,自定义的类也可以 Student
不写泛型默认为Object类型。
public class 类名 { 方法; }
类名<类型> 对象名 = new 类名<>( );
继承:
public class 类名 extends A { }
含有泛型的方法
泛型定义的方法在修饰符和返回值类型之间。
修饰符 <泛型> 返回值类型 方法名 (参数列表(使用泛型) ) { 方法体; }
public void demo ( M m ) { m.xxx; }
直接传递参数
含有泛型的静态方法:
public static void demo ( M m ) { m.xxx; }
静态方法,不建议创建对象,使用类名.静态方法名( xx ); 进行使用。
含有泛型的接口:
public interface Demo { 抽象方法;E next();E get();add(E e); }
使用方式:
定义接口实现类,指定接口的泛型 : xx implements Demo
接口使用什么泛型,实现类就使用什么泛型,相当于定义了一个含有泛型的类。
public class 类名 extends A implements Demo { }
类名<类型> 对象名 = new 类名<>( );
泛型通配符
未知通配符:不知道使用什么类型接受数据,只能接受,不能存储数据。
使用:遍历集合
?代表任务的数据类型,只能作为方法的参数使用
public static void printA (ArrayList<?> list) {
//使用迭代器遍历:
Iterator<?> it = list.iterator();
while(it.hasNext( ) ){ Object o = it.next();
} }
- 1
- 2
- 3
- 4
- 5
- 6
注意:定义时不能使用:ArrayList<?> x = new ArrayList<?> () ; 错误
受限泛型
泛型的上限:只能接受该类型及其子类,? extends E
类型名 <? extends 类 > 对象名称
泛型的下限:只能接受该类型及其父类:? super E
类型名 <? super 类 > 对象名称
数据结构
栈:先进后出,LinkedList stack = new LinkedList<>();
stack.addLast(1); stack.removeLast(); // 出栈
队列:先进先出,Queue queue = new LinkedList<>();
queue.offer(1); // 元素 1 入队 queue.poll(); // 出队 -> 元素 1
数组,查询快(数组的地址是连续的),增删慢(数组长度固定不变,添加要复制新数组,,再把新数组地址赋值给变量,原数组进行垃圾回收)
int[] a = new int[3]{1,2,3,4};
链表:查询慢(每一个元素为一个节点,一个节点包含数据源+两个指针域,自己的地址和下一个节点地址),增删快。LinkedList:List接口的链表实现
单向链表:不能保证元素顺序
双向链表:有一个链子是记录顺序的,是有序的集合
红黑树:
二叉树:分支不能超过两个孩子
排序树/查找树:在二叉树的基础上,元素的是有顺序的。左子树小,右子树大。
平衡二叉树:左孩子数量==右孩子数量
红黑树:特点:趋近于二叉树,查询速度非常快,查询叶子节点最大次数和最小次数不能超过2倍。
约束:节点可以是红色或者黑色的,
根节点是黑色的,
叶子节点是黑色的,
每一个红色的节点的子节点都是黑色的
任何一个节点到每一个叶子节点的所有路径上的黑色节点数量相同。
List集合
java.util.list
Collection集合的子类,List接口继承Collection接口
1.有序的集合 2.有索引3.允许存储重复数据
创建多态:List list = ArrayList<>();
list.add(int index, E element)
E remove(int index) //返回被移除的元素
E set(int index) // 替换集合中指定位置的元素,返回被替换的元素
E get(int index)
List遍历
for:list.size().fori
迭代器:Iterator it = new Iterator<>();
while(it.hasNext( ) ) { it.next(); }
增强for即foreach
List.for
防止索引越界:IndexOutOfBoundException,集合会报错
List子类
ArrayList集合查找快,增删慢。 结构是数组结构。
ArrayList<Person> list = new ArrayList<>();
list .add( new Person("XXX" , 11));
- 1
- 2
LinkedList:List接口的链表实现,双向链表,查询慢,增删快,包含了对首尾操作的方法,使用特有方法时不能使用多态。
添加元素:addFirst列表开头插入== push ( ) ,addLast列表结尾插入== add,
获取元素:getFirst(),getLast()
清空元素:clean()
isEmpty是否为空
removeFirst( ) == pop( ),removeLast( )
Set集合
不包含重复元素的集合,没有索引,不能使用for循环
HashSet
实现了set接口,是一个无序的结合,存储元素和取出元素顺序可能不同
底层是一个哈希表(HashMap)结构,查询非常快
Set s = new HashSet<>();
HashSet s = new HashSet<>();
使用迭代器进行遍历
迭代器:Iterator it = new Iterator<>();
while(it.hasNext( ) ) { it.next(); }
增强for:
哈希值
是一个十进制的整数,系统随机给出,对象的地址值,是一个逻辑地址,是模拟出来的,不是实际的物理地址。
Object类的方法,获取哈希值:int hashCode()
hashCode的源码:public native int hashCode(),native调用本地操作系统的方法。
toString返回的是hashCode的十六进制的值。不是实际的物理地址
String类的哈希值:重写了Object的hashCode的方法。
哈希表结构
HashSet集合存储数据的结构,查询速度快。
哈希表 = 数组 + 链表
哈希表 = 数组 + 红黑树
数组把元素进行分组,相同的哈希值是同一组,链表/红黑树将这些组进行连接到一起,挂到当前哈希值数组下。
哈希冲突:两个元素不同,但是哈希值相同。
如果链表的长度超过8位数,将链表转换为红黑树,提升查询效果
Set集合元素不重复
出现哈希冲突,使用equals进行判断元素地址值,如果元素地址相同,就不存储进去。如果元素不相同,就存储进去。使用链表或者红黑树进行挂在同一个哈希值下面。
HashSet存储自定义类型元素
必须重写hashCode方法和equals方法,因为要比较值
在自定义类中进行重写。
LinkedHashSet
定义了迭代顺序,是双向列表,记录元素的存储顺序,保证元素有序,且元素不重复
LinkedHashSet s = new LinkedHashSet<>();
可变参数
修饰符 返回值类型 方法名 (参数类型 … 形参名) { }
等价于:修饰符 返回值类型 方法名 (参数类型 [ ] 形参名) { }
使用环境:当方法的参数列表数据类型已去掉,参数个数不确定。
原理:底层是一个数组,根据传递参数个数的不同,创建不同长度数组,存储参数。
public static int add ( int ... arr) {
int sum = 0;
for (int i : arr) { sum += i ; }
return sum; }
- 1
- 2
- 3
- 4
调用add ( ) 会创建一个长度为0的数组 arr,new int [ 0 ]
注意:
1.一个方法的参数列表,只能有一个可变参数
2.如果方法的参数有多个,可变参数写在参数列表末尾
3.特殊写法:public static void method ( Object … obj) { }
Collections
集合工具类,对集合进行操作
随机排序:shuffle(List) Collections.shuffle( );
public static boolean addAll ( Collection c, T … elements) 添加一些元素
: Collections.addAll (list , 1, 2, 3);
public static void sort ( List list) 默认升序 :Collections.sort(list);
sort 使用前提:被排序的集合里面存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序规则。
例如:
public class Person implements Comparable<Person> {
@Override
public int compareTo(Person o){
//自定义比较规则
return this.getAge - o.getAge ( ) ; // 年龄升序排序
} }
- 1
- 2
- 3
- 4
- 5
- 6
Comparable排序规则:自己(this)- 参数:升序,参数- 自己(this):降序this - o > 0 ,则compareTo返回这个数,sort进行升序排列,把o的值放在序列前面
sort (List , Comparator)
public static void sort ( List list,Comparator<? super T>)
传一个集合和一个比较器
Comparable与Comparator
Comparable:自己(this)与别人(参数)进行比较,自己需要实现Comparable接口,重写比较规则compareTo方法,强行对实现它的每个类的对象进行整体排序。
Comparator:找到第三方的裁判进行比较,强行对某个对象进行整体排序。
Comparator要重写compare< T o1, T o2> 方法,o1 - o2 升序
Arrary.sort( list, new Comparator<Person> {
@Override
public int compare(Person o1, Person o2){
//自定义比较规则
return o1.getAge() - o2.getAge () ; // 年龄升序排序
} } ); //匿名内部类 new 接口()
//lambda
Arrary.sort( list, (o1, o2) -> o1.getAge() - o2.getAge( ) ); //匿名内部类 new 接口()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
文章来源: blog.csdn.net,作者:αβγθ,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/weixin_38022166/article/details/115381884
- 点赞
- 收藏
- 关注作者
评论(0)