目前听完了 课程40前四章 内容
- Collection
- List
- LinkedList
- HashSet
- LinkesHashSet
- TreeSet
- Map
- HashMap
数组,集合都是对多个数据进行存储操作的,简称为容器 这里的存储指的是内存层面的存储,而不是持久层存储(例持久层存储 如.txt,.avi,.jpg,数据库)
前后端与数据库之间关联方式
Collection
public class collection {
public static void main(String[] args) {
/*
collection接口常用方法:
增加 add(E e) addAll(Collection<? extends E> c)
删除 clear() remove(Object o)
修改
查看 iterator() size()
判断 contains(Object o) equals(Object o) isEmpty()
== 比较的是地址 equals比较的是内容
*/
//接口不能创建对象 利用实现类创建对象
Collection col=new ArrayList();
//集合特点 只能存放引用数据类型 不能存放基本数据类型
//基本数据类型自动装箱 对应包装类 int->Integer
col.add(18);
col.add(19);
//对集合遍历
for (Object o:col){
System.out.println(o);
}
//对集合遍历
Iterator it=col.iterator();
while (it.hasNext()){
//it相当于指针 通过hasNext()来判断是否有下一个元素 有返回true 没有返回false
System.out.println(it.next());//it.next()输出指针指向对值,指针向后移动一个位置
}
System.out.println(col);
List list=Arrays.asList(new Integer[]{11,23});
col.addAll(list);
boolean isremove=col.remove(15);
col.clear();
}
}
List
public class list {
public static void main(String[] args) {
/*
List接口中常用方法:
增加 add(int index,E element)
删除 remove(int index) remove(Object o)
修改 set(int nde,E element)
查看 get(int index)
判断
*/
//接口不能创建对象,可以用接口实现类创建对象,可以用接口对实现类创建对象,
//把创建后的对象作为接口创建的对象
List list=new ArrayList();
list.add(1);
list.add(14);
list.add(2);
list.add(3,66);
list.set(2,77);
//在集合中存入的是Integer类型数据,调用remove调用的是remove(int index)
System.out.println(list);
Object o=list.get(0);
//遍历1
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
//遍历2
for(Object a:list){
System.out.println(a);
}
//遍历3
Iterator it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
ArrayList d=new ArrayList();
d.add(13);
}
}
泛型
一般在使用时基本上往集合中存入的都是相同类型的数据,便于管理,所以现在什么引用数据类型都可以存入集合,不方便
泛型相当于标签,集合容器类在设计阶段/声明阶段不能确定这个容器到底是寄存的是什么类型的对象,所以在JDK1.5之前,只能把元素类型设计为Object。JDK1.5之后,使用泛型来解决。因为这个时候除了元素的类型,不确定其他的部分是确定的,例如关于这个元素如何保存如何管理等是确定的。Collection,List,ArrayList就是这个就是类型参数,即泛型。加入泛型的优点,在编译时期就会对类型进行检查。
泛型只是对编译器进行了限制,比如ArrayLista=new ArrayList();只是在编译时限制了在a中只能加Integer类型数据,但是在底层看,a是可以加Object类型数据的。
ArrayList<Integer>a=new ArrayList<Integer>();
a.add(1);
//JDK1.7后可以写为
ArrayList<Integer>b=new ArrayList<>();
泛型类实例化
public class test<E> {
int age;
E sex;//sex的类型与test相同
public void a(E n){
}
public void b(E[] m){
}
}
//指定父类泛型 子类就不需要再指定泛型
class subtest extends test<Integer>{
}
//如果父类不指定泛型,子类也会变成一个泛型类
class subtest2<E> extends test<E>{
}
class Test{
public static void main(String[] args) {
//1.实例化的时候不指定泛型,那么认为泛型为Object
test A=new test();
A.a("123");
A.a(123);
//2.实例化指定泛型 推荐
test<String> B=new test<>();
B.a("123");
B.b(new String[]{"a","b","c"});
subtest s=new subtest();
s.a(1);
}
}
定义的参数类型可以是多个
泛型可以使用多个字母
不可以 A[] i=new A[10];
泛型类的静态方法不能使用类的泛型
//泛型可以使用多个字母
public class multi<A,B,C>{
A age;
B name;
C sex;
public void a(A m,B n,C x){
//不可以 A[] i=new A[10];
A[] i=(A[])new Object[10];
}
//泛型类的静态方法不能使用类的泛型
/*
因为 static是先于对象加载的,等创建完对象,才会给泛型定义,
而在泛型静态方法中如果已经使用了还未加载的泛型定义 则会报错
public static int c(A a){
*/
}
泛型方法
泛型方法不是带泛型的方法,而是这个方法的泛型的参数类型和当前的类的泛型无关
public class multi<A,B,C>{
//不是泛型
public void t(A a){
}
//是泛型
public <T> void b(T t){
}
}
A和B是子类父类关系,但是G和G不存在继承关系,是并列关系,因为在编译的时候只允许输入A和B类型数据,但是在底层都是Object类型
Object obj=new Object();
String s=new String();
obj=s;//多态
List<Object>l1=new ArrayList<>();
List<String>s1=new ArrayList<>();
在没有通配符的时候:
下面的a方法相当于方法的重复定义,报错
public void a(List<?> list){
//遍历类型用Object接收,不用?接收
for(Object o:list){
}
//只能写入null,因为不知道对象赋给?什么类型数据
list.add(null);
//数据读取操作
Object s=list.get(0);
}
public static void main(String[] args) {
List<Object>list1=new ArrayList<>();
List<String>list2=new ArrayList<>();
List<?>list=null;
list=list1;
list=list2;
}
泛型受限
泛型上限
泛型下限
class Test{
public void a(List<?> list){
}
public static void main(String[] args) {
List<Object>a=new ArrayList<>();
List<person>b=new ArrayList<>();
//stu是person子类
List<stu>c=new ArrayList<>();
//泛型受限:泛型上限是person
List<? extends person>list1=null;
list1=b;
list1=c;
//泛型受限:泛型下限是person
List<? super person>list2=null;
list2=a;
list2=b;
}
}
LinkedList
poll和remove区别:
当LinkedList里面数据,poll不会报错remove会报错
public class linkedList {
/*
LinkedList常用方法
增加 addFirst(E e) addList(E e) offer(E e) offerFirst(E e)
删除 poll() pollFirst() removeFirst() removeLast()
修改
查看 element() getFirst() getLast() indexOf(Object o)
LastIndexOf(Object o)
peek() peekFirst() peekLast()
清空 clear()
*/
public static void main(String[] args) {
LinkedList<Integer>list=new LinkedList<>();
list.add(123);
list.add(234);
list.addFirst(1);
//遍历1
for (int i=0;i<list.size();i++)
System.out.println(list.get(i));
//遍历2
for (Integer i:list)
System.out.println(i);
//遍历3
for (Iterator<Integer>it=list.iterator();it.hasNext();)
System.out.println(it.next());
System.out.println(list.getFirst());
list.poll();
System.out.println(list.getLast());
list.clear();
//区别
System.out.println(list.pollLast());//null
//System.out.println(list.removeLast());//报错
}
}
LinkedList简要原理图
底层是个双向链表
ArrayList,List,Collection,Iterable,Iterator之间的关系
listIterator
报错
while (it.hasNext()){
//报错,原因是 list和it同时操作list
//it.next()会操作list list.add操作list
if("1".equals(it.next())){
list.add("ni hao");
}
}
由于上述报错,引入listIterator,迭代和add都是靠listIterator完成的
public static void main(String[] args) {
List list=new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add(3,"5");
ListIterator<String> it=list.listIterator();
while (it.hasNext()){
if("1".equals(it.next())){
it.add("ni hao");
}
}
System.out.println(it.hasNext());//返回false 下面没有元素了
System.out.println(it.hasPrevious());//true 上面有元素
//逆向遍历
while (it.hasPrevious())
System.out.println(it.previous());//5 3 2 ni hao 1
}
HashSet
放入自定义引用数据类型,不满足唯一,无序的特点,原因是:在自定义引用数据类型中没有重写hashCode和equals方法
HashCode原理图:
在集合中存入数据,调用对应的hashCode方法计算哈希值,通过哈希值和一个表达式计算在数组中存放的位置,如果存放的位置已经有值了且与该值不同,链接到后,如果已经存在,不链接
LinkedHashSet
在Hashset基础上,多了一个总的链表,这个总链表将放入的元素串在一起
TreeSet
唯一,升序
底层是二叉树
自定义类需要实现比较器
通过内部比较器来比较
接口文件
package java.lang;
import java.util.*;
public int compareTo(T o);
}
stu类
public class stu implements Comparable<stu>{
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "stu{" +
"age=" + age +
", name='" + name + ''' +
'}';
}
private int age;
private String name;
stu(int age,String name){
this.age=age;
this.name=name;
}
public int compareTo(stu o){
return this.getAge()-o.getAge();
}
}
测试类:
import java.util.TreeSet;
public class test1 {
public static void main(String[] args) {
TreeSet<stu>t=new TreeSet<>();
t.add(new stu(10,"d"));
t.add(new stu(11,"DA"));
System.out.println(t);
System.out.println(t.size());
}
}
### 通过外部比较器来比较
Map
Map无序唯一
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class map {
/*
增加 put(K key V value)
删除 clear() remove(Object key()
查看 entrySet() get(Object key) keySet() size() values()
判断 containsKEy(Object key) containsValue(Object value)
equals(Object o) isEmpty()
*/
public static void main(String[] args) {
Map<Integer,String>mp=new HashMap<>();
mp.put(123,"q");
mp.put(234,"hi");
System.out.println(mp.containsKey(123));
System.out.println(mp.containsValue("hi"));
System.out.println(mp.get(123));
Set<Integer>set=mp.keySet();//对集合中对set遍历
for (Integer i:set){
System.out.println(i);
}
Collection<String>value=mp.values();
for (String s:value){
System.out.println(s);
}
Set<Map.Entry<Integer,String>>entries=mp.entrySet();
for (Map.Entry<Integer,String> e:entries){
System.out.println(e.getKey()+e.getValue());
}
}
}
# Map
增删查改
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class map {
/*
增加 put(K key V value)
删除 clear() remove(Object key()
查看 entrySet() get(Object key) keySet() size() values()
判断 containsKEy(Object key) containsValue(Object value)
equals(Object o) isEmpty()
*/
public static void main(String[] args) {
Map<Integer,String>mp=new HashMap<>();
mp.put(123,"q");
mp.put(234,"hi");
System.out.println(mp.containsKey(123));
System.out.println(mp.containsValue("hi"));
System.out.println(mp.get(123));
Set<Integer>set=mp.keySet();//对集合中对set遍历
for (Integer i:set){
System.out.println(i);
}
Collection<String>value=mp.values();
for (String s:value){
System.out.println(s);
}
Set<Map.Entry<Integer,String>>entries=mp.entrySet();
for (Map.Entry<Integer,String> e:entries){
System.out.println(e.getKey()+e.getValue());
}
}
}
内部比较器
public class stu implements Comparable<stu>{
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "stu{" +
"age=" + age +
", name='" + name + ''' +
'}';
}
private int age;
private String name;
stu(int age,String name){
this.age=age;
this.name=name;
}
public int compareTo(stu o){
return this.getName().compareTo(o.getName());
}
}
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class test1 {
public static void main(String[] args) {
Map<stu,Integer>mp=new TreeMap<>();
mp.put(new stu(18,"wxy"),1);
mp.put(new stu(19,"wbb"),2);
mp.put(new stu(17,"dfg"),1);
System.out.println(mp);
}
}
外部比较器
public class stu{
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "stu{" +
"age=" + age +
", name='" + name + ''' +
'}';
}
private int age;
private String name;
stu(int age,String name){
this.age=age;
this.name=name;
}
}
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class test1 {
public static void main(String[] args) {
Map<stu,Integer>mp=new TreeMap<>(new Comparator<stu>() {
@Override
public int compare(stu o1, stu o2) {
return (((Integer)(o1.getAge())).compareTo((Integer)(o2.getAge())));
}
});
mp.put(new stu(18,"wxy"),1);
mp.put(new stu(19,"wbb"),2);
mp.put(new stu(17,"dfg"),1);
System.out.println(mp);
}
}
HashMap
原理
1.调用hashCode方法,算出哈希值
2.将哈希值带入某算法计算出在数组中的位置
3.当发生哈希冲突,使用头插法把新节点插到相同哈希值元素的前面