泛型
1.概述
泛型标志 <> 常用来约束集合中的元素类型 ,并且能把报错的时机提前
2. 使用案例
public class Test4_Generic {
public static void main(String[] args) {
Integer[] a = {1,2,3,4,5};
Double[] b = {1.1,2.2,3.3,4.4,5.5};
String[] c = {""};
print(a) ;
print(b) ;
print(c) ;//1、问题是:又得提供重载的print()!!
}
//2、以前参数列表,写死了,必须是具体类型。泛型写出通用代码,只要是E泛型类型就行。
public static <E> void print(E[] a) {
// for (int i = 0; i < a.length; i++) { System.out.println(a[i]); }
//foreach语法:提高普通for循环的执行效率 + 语法简洁
//for( 获取到的数据类型 变量名 : 想要循环的数组名){ 循环体 }
for( E in : a ){
System.out.println(in);//in表示当前获取到的数据
}
}
}
集合
1. 作用
- 用来存储多个数据,集合中把每个数据叫做元素
- 继承结构 Collection接口 是集合中的顶级接口 ,提供的方法被子类或者实现类使用
- 下属有两个子类接口 :List接口 Set接口
1.1 Collection 提供的共有方法
Collection<String> c = new ArrayList<>();
Collection<String> c1 = new ArrayList<>();
//2、常用方法
c.add("jack");//添加元素
c.add("rose");
c.add("hanmeimei");
c.add("lilei");
c.clear();//清空集合
c.contains("abc");//是否包含指定字符串
c.equals("hanmeimei");//是否相等
c.isEmpty();//是否为空
c.remove("lilei");//删除指定元素
c.size();//获取集合长度
Object[] obj= c.toArray();//把集合中的元素放入数组
c.addAll(c1);//添加另一个集合
c.containsAll(c1);//是否包含另一个集合
c.removeAll(c1);//删除另一个集合(差集)
c.retainAll(c1);//删除另一个集合(交集)
//3.集合的迭代
Iterator<String> it =c.iterator();//迭代器
while(it.hasNext()){ //判断集合是否还有下一个元素
String value = it.next();//next() 获取迭代到的元素
System.out.println(value);
}
2.List接口
有序的collection(也被称之为序列)。此接口可以对列表中的每个元素的插入位置进行精确的控制。
用户可以根据元素的下标发访问元素 与set不同 列表中允许有重复元素 下属实现类 ArrayList LinkedList。
特点:
- 有序的
- 有索引
- 允许重复
2.1 ArrayList 特有方法
List<String> list =new ArrayList<>();
list.add("java");
list.add("php");
list.add("hadoop");
list.add("hadoop");
list.add(null);
list.add(0,"aaaa");//在指定位置添加元素
list.get(1);//获取指定索引存着的元素
list.indexOf("php");//获取指定元素的下标
list.lastIndexOf("php");//获取指定元素最后一次出现的下标
list.remove(1);//把指定索引的值删除
list.remove("php");//删除指定值 如果是数字 必须是包装类型
list.remove(Integer.valueOf(1));//删除集合中的1
list.set(0,"bbb");//将指定下表处的值替换掉
List<String> list2 = list.subList(1,3);//截取list集合 含头不含尾;
list集合的迭代
//1.可以通过 父类方法 iterator进行迭代
Iterator<String> it = list.iterator<>();
while(it.hasNext()){
System.out.println(it.next());
}
//2.可以通过list特有迭代器进行迭代
//特有的不仅能向后顺序遍历而且可以向前逆向遍历
ListIterator<String> it1 = list.listIterator<>();
while(it.hasNext()){
...
}
//3.通过for循环 和 增强foreach 进行迭代
LinkedList
是list接口的实现类 底层是一个链表实现 ,不适用于查询 ,适用于增删业务
特有方法
void addLast(E e)
将指定元素添加到此列表的结尾。
E removeFirst()
移除并返回此列表的第一个元素。
E removeLast()
移除并返回此列表的最后一个元素。
E getFirst()
返回此列表的第一个元素。
E getLast()
返回此列表的最后一个元素。
E element()
获取但不移除此列表的头(第一个元素)。
boolean offer(E e)
将指定元素添加到此列表的末尾(最后一个元素)。
boolean offerFirst(E e)
在此列表的开头插入指定的元素。
boolean offerLast(E e)
在此列表末尾插入指定的元素。
E peek()
获取但不移除此列表的头(第一个元素)。
E peekFirst()
获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast()
获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null
E poll()
获取并移除此列表的头(第一个元素)
E pollFirst()
获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast()
获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pop()
从此列表所表示的堆栈处弹出一个元素。
void push(E e)
将元素推入此列表所表示的堆栈。
package cn.tedu.collection;
import java.util.LinkedList;
//这个类用例测试 LinkedList
public class Test2_LinkedList {
public static void main(String[] args) {
//1、创建LinkedList对象
LinkedList<Integer> ll = new LinkedList<>() ;
//TODO 2、继承来的方法调用
ll.add(1);
ll.add(2);
ll.add(3);
ll.add(4);
ll.add(5);
//3、特有方法
ll.addFirst(99); //添加首元素
ll.addLast(100);//添加尾元素
System.out.println(ll);
System.out.println( ll.getFirst() );//获取首元素
System.out.println( ll.getLast() );//获取尾元素
System.out.println( ll.removeFirst() );//移除首元素
System.out.println( ll.removeLast() );//移除尾元素
System.out.println(ll);
}
}
Set
### 1.概念
一个不包含重复元素的集合 ,并且最多包含一个null元素
### 2.特点:
- 元素不重复
- 元素无需
- 元素没索引
package cn.tedu.collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
//这个类用来测试 Set接口:元素不能重复 + 元素是没有下标的 + 元素无序
public class Test3_Set {
public static void main(String[] args) {
//1、创建对象
Set<Integer> set = new HashSet<>();
//TODO 2、常用方法
set.add(1);
set.add(3);
set.add(2);
set.add(1);
set.add(2);
//set中不能存放重复元素,常用来去重!!
System.out.println(set);
//3、迭代
Iterator<Integer> it = set.iterator() ;
while(it.hasNext()) {//判断是否有下一个元素
Integer value = it.next() ;//获取元素并把指针后移
System.out.println(value);
}
//foreach for(获得的数据类型 遍历名 : 数组|Collection集合 ){ }
for(Integer in : set) {
System.out.println(in);
}
}
}
HashSet
### 是set接口的实现类 可以使用set接口的所有功能
### 底层是哈希表/散列表 ,实际上底层维护了一个hashmap
### 实例的默认初始容量是 16,加载因子是 0.75。
package cn.tedu.collection;
import java.util.HashSet;
//这个类用来测试 利用set集合去重
//总结:
//1、set集合常用于去重
//2、如果想利用set集合给自定义对象去重。需要同时提供重写的hashCode() 和 equals() !!!
//3、重写hashCode():是为了让底层运算哈希值时,可以根据对象的属性值运算。
//如果两个对象的属性值一样,即将得到相同的hash值
//4、重写equals():是为了让底层在判断两个对象是否相等时,可以根据对象间的属性值判断。
//如果两个对象的属性值一样,就认为是相等的,让equals()返回true
public class Test5_HashSet2 {
public static void main(String[] args) {
//1、创建HashSet对象
HashSet<Student> set = new HashSet<>();
Student s1 = new Student("jack",18);
Student s2 = new Student("rose",20);
Student s3 = new Student("tony",30);
//2、加入set中
set.add(s1);
set.add(s2);
set.add(s3);
//3、set集合不是可以去重吗?-- 能不能把自定义的对象去重呢?-- 暂时没去重!!
Student s4 = new Student("jack",18);
//4、怀疑add()在添加自定义的对象时,没有根据属性去重!!
//if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
//5、为了使两个对象间的hash值一致,我们需要把只要new一次就计算一个hash值这种默认实现方式改掉。
//这时,需要重写hashCode()让此方法运算出来的hash值可以根据对象的属性值运算。
set.add(s4);
System.out.println(s1.hashCode());
System.out.println(s4.hashCode());
System.out.println(set);
}
}
//创建Student类
class Student{
public Student() {}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
private String name ;
private int 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 + "]";
}
//右键-source-generator equals() and hashCode()-ok
//5、为了使两个对象间的hash值一致,我们需要把只要new一次就计算一个hash值这种默认实现方式改掉。
//这时,需要重写hashCode()让此方法,运算出来的hash值可以根据对象的属性值运算。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//6、为了让两个对象间,比较属性值,需要提供重写的equals()
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Map接口
### 1.概述
map接口也是集合的一种形式,只不过和Collection接口没什么关系
map接口有两个实现类 重要的时hashmap 里面存放的都是键值对
HashMap的原理:HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
2.特点
- map里面的数据都是 key value 结构
- map里面的key不能重复 ,如果可以重复,会把value值覆盖掉
- map无序
- map里面的value可以根据key获的
3.常用方法
package cn.tedu.collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
//这个类用来测试 Map接口:数据无序 + key不能重复如果重复value会被覆盖
public class Test6_Map {
public static void main(String[] args) {
//1、创建Map对象
Map<Integer,String> map = new HashMap<>();
//2、常用方法
map.put(9527, "唐伯虎") ;
map.put(9529, "钟南山") ;
map.put(9530, "袁隆平") ;
map.put(9528, "如花") ;
map.put(9528, "刘沛霞") ;//key相同,value会被覆盖
System.out.println(map);
// map.clear();
System.out.println( map.containsKey(9528) );//判断是否包含指定的key
System.out.println( map.containsValue("tony") );//判断是否包含指定的value
System.out.println( map.equals("tony") );//判断是否相等
System.out.println( map.get(9527) );//根据key获取对应的value
System.out.println( map.hashCode());//获取map在内存中的哈希码值
System.out.println( map.isEmpty());//判断是否为空
System.out.println( map.remove(9528));//根据key删除记录,并返回对应value
System.out.println( map.size());//获取集合的长度
Collection<String> values = map.values() ;//把map集合的value们存入Collection中
System.out.println(values);
//3.迭代map集合 ---需要把map转换成为set 调用 keySet方法
Set<Integer> set = map.keySet();
for(Integer key:set){
String value = map.get(key);
}