目录
(2)为什么使用泛型?我们原来在定义集合时,是如下得定义方式:
1.集合框架的概念
Java集合框架(Java Collections Framework简称JCF)是为表示和操作集合,而规定的一种统一的标准的体系结构。集合框架包含三大块内容:对外的接口、接口的实现和对集合运算的算法。数组和集合的区别:数组是定长的,集合是不定长的。
集合和数组的区别
数组和集合相比,数组的缺点是它长度是固定的,没有办法动态扩展。
而集合存储数据时是没有长度限制的,是可以动态扩展的。集合容器因为内部的数据结构不同,有多种不同的容器对象。这些容器对象不断的向上抽取,就形成了集合框架。
2.Collection集合
Collection接口是单值集合的顶层接口,它的继承关系如下。
2.1 Collection集合默认可以存储任何类型的元素
2.2 Collection可以重复添加,并且可以存储空值null
2.3 不能根据下标获取单个元素
2.4 Collection的方法使用
Collection coll = new ArrayList();//定义Collection接口变量,指向其实现对象Arraylist
coll.add("a");//添加String类型的a
coll.add(5);//添加整形的5
coll.add('b');//添加char类型的b
Collection colls = new ArrayList(2);
colls.add(2);
colls.add(3);
coll.addAll(colls);
System.out.println(coll);
boolean b = coll.containsAll(colls);//判断coll中是否包含colls中的所有元素
System.out.println(b);
int size = coll.size();//获取coll的长度
System.out.println(size);
coll.remove(5);//删除2这个元素
coll.removeAll(colls);//批量删除coll中的colls的元素
System.out.println(coll);
boolean empty = coll.isEmpty();//判断coll是否为空
System.out.println(empty);
coll.clear();//清除coll中的所有元素
boolean empty1 = coll.isEmpty();
System.out.println(empty1);
3.List
3.1 List集合是有序集合: 数据的添加和存储次序一致, List集合可以存储重复的数据, List集合中的数据可以通过下标访问
3.2 ArrayList实现类的用法
特点:
- 实现了List接口
- 可以动态扩容(我们只管存,长度不够,底层会自动的扩容)
- 通过下标可以快速访问数据
- 查找快,插入删除慢
- ArrayList底层是数组,对数组做了封装
- 可以存储任意类型的数据,包括null
- 数据按照存储次序排列
- 数据可以重复
- 多线程访问时不安全
实现了list接口,可以动态扩展,可以使用下标进行访问数据,查找较快,删除和插入较慢,ArrayList的底层就是数组,对数组进行了封装,多线程访问的时候是不安全的。
List list = new ArrayList(5);//创建长度为五的Arraylist对象
list.add("a");//在集合中添加一个String类型的a
list.add(5);//在集合中添加一个整形的数字5
list.add('a');//添加一个char类型的a
list.add(new Date());//添加一个Date类型的数据
list.add("a");//可以添加重复的数据
//当添加的内容超过数组的长度后会自动扩容
list.add("菠萝是种好水果");
System.out.println(list);//输出集合的内容
list.set(3,"好水果");
list.remove(new Date());//移除集合中的Date数据
System.out.println(list);
list.remove(1);//移除下标为1的内容
List listTwo = new ArrayList(2);
listTwo.add("凤梨");
listTwo.add(1,"哈哈哈哈");
list.addAll(listTwo);//将集合listTwo中的所有内容添加到list集合中
System.out.println(list);
System.out.println(list.contains("菠萝是种好水果"));//查找集合中是否存在“菠萝是种好水果”
System.out.println(list.containsAll(listTwo));
list.get(2);//获取下标为2的内容
list.indexOf("a");//查找a首次出现的位置
System.out.println(list.size());//输出集合的长度
System.out.println(list.isEmpty());//判断集合是否为空
int i = list.hashCode();//返回list的哈希码值
System.out.println(i);
list.clear();//清空集合
3.3LinedList和Vector实现类的用法
LinkedList: 具有List的特征,底层以链表结构实现,可以进行头尾元素的添加删除
Vetor: 与ArrayList功能一致,在多线程环境下,比ArrayList安全。查询效率高,增加删除效率低,性能比较低。
LinkedList linkedList=new LinkedList();
linkedList.add("a");//添加字符型的a
linkedList.add(5);//添加整型数据
linkedList.add(new Date());//添加时间类型数据
linkedList.addFirst(1);//在头部添加数据
linkedList.addLast("尾");//在尾部添加数据
linkedList.set(2,"hello");//在下标为2的地方插入元素
System.out.println(linkedList.get(2));//获取下标为2的元素内容
linkedList.getFirst();//获取第一个数据 即linkedlist【0】
linkedList.getLast();//获取最后一个元素的内容
LinkedList linked = new LinkedList(); //LinkedList不能指定长度
linked.add(11);
linked.add(10);
linkedList.addAll(linked);//批量添加元素 即添加linked中是所有元素
System.out.println(linkedList);
linkedList.remove(2);//删除下标为2的元素的内容
System.out.println(linkedList);
System.out.println(linked);
linkedList.addAll(0,linked);//在下标为2的地方放批量插入数据
System.out.println(linkedList);
linkedList.removeFirst();//删除头部元素
linkedList.removeLast();//删除尾部元素
System.out.println(linkedList);
4 Set
Set接口特点
- Set接口是无序的
- Set接口中的数据不允许重复
- Set接口无法通过下标访问数据
- 查找慢,插入删除快(底层数据结构是哈希表和红黑树)
- Set集合使用equals()和hashCode()方法实现元素去重
4.1.set是无序且不能重复的,他是一个接口,它包含HashSet和TreeSet两个部分。底层逻辑是hashMap
4.2.HashSet的使用方法如下:
HashSet特点:
- HashSet是Set接口的实现类
- 线程不安全
HashSet hashSet = new HashSet();//默认的长度是16
HashSet hashSet1 = new HashSet(5);//可以指定长度
HashSet hashSet2 = new HashSet(15,0.7f);
//其中15表示长度,0.7表示负载因子,即当资源使用达到70%的时候会自动扩容
hashSet.add(1);//添加数字1
hashSet.add("A");
hashSet.add("B");
hashSet.add('A');
hashSet.add("A");
System.out.println(hashSet);//当添加的内容有重复时会自动舍弃,因为hashset是不可重复的,根据输出来看hashSet是无序的
hashSet1.add("喜洋洋");
hashSet1.add("海绵宝宝");
hashSet1.add("暖洋洋");
hashSet.addAll(hashSet1);//批量添加元素,即将hashSet1中的所有元素都添加到hashSet中,
System.out.println(hashSet);
int size = hashSet.size();//获取长度
System.out.println(size);
boolean a = hashSet.contains("A");//判断A是否在hashSet集合中
System.out.println(a);
boolean empty = hashSet.isEmpty();//判断是否为空
System.out.println(empty);
hashSet.remove("灰太狼");//移除孙传芳
System.out.println(hashSet);
//foreach方式遍历hashSet集合
for (Object o:hashSet) {
System.out.print(o+"\t");
}
System.out.println("\n"+"——————————————————————————我是分割线————————————————————————");
//使用迭代器遍历
Iterator iterator = hashSet.iterator();//获取迭代器对象
while (iterator.hasNext()){//判断指针是否能够移动
System.out.print(iterator.next()+"\t");//输出当前指针所指的元素.next表示获取当前指针所指的元素
}
HashSet避免对象重复的规则:
1)如果对象的hashCode值不同,则不用判断equals方法,就直接存到HashSet中。
2)如果对象的hashCode值相同,需要用equals方法进行比较,如果结果为true,则视为相同元素,不存储。如果结果为false,视为不同元素,进行存储。
注意:如果对象元素要存储到HashSet中,必须覆盖hashCode方法和equals方法。才能保证从对象中的内容的角度保证唯一。
TreesSet特点:
- 有序
- 不重复
- 添加、删除、判断元素存在性效率比较高
- 线程不安全
TreeSet对元素进行排序的方式:
1) 如果是基本数据类型和String类型,无需其它操作,可以直接进行排序。
2) 对象类型元素排序,需要实现Comparable接口,并覆盖其compareTo方法。
3) 自己定义实现了Comparator接口的排序类,并将其传给TreeSet,实现自定义的排序规则
4.3.TreeSet的底层逻辑是二叉树,TreeSet可以实现有序集合,但是有序需要通过比较器实现
4.4.TreeSet的使用方法:和hashSet一模一样
TreeSet 基于TreeMap 实现。TreeSet可以实现有序集合,但是有序性需要通过比较器实现。
TreeSet treeSet = new TreeSet();
treeSet.add("A");
treeSet.add("B");
treeSet.add("C");
treeSet.add("D");//添加元素
TreeSet treeSet1 = new TreeSet();
treeSet1.add("慢走");
treeSet1.add("欢迎下次再来");
treeSet.addAll(treeSet1);//批量添加元素
System.out.println(treeSet);
System.out.println(treeSet.size());//输出treeSet的长度
treeSet.remove("D");//删除D
4.5比较器的实现方法
当添加对象类型的数据时需要指定比较器
public class Test03 {
public static void main(String[] args) {
TreeSet treeSet=new TreeSet();
treeSet.add(new Student("张三",15));
treeSet.add(new Student("李四",16));
treeSet.add(new Student("王五",18));
treeSet.add(new Student("麻叶子",15));
System.out.println(treeSet);
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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;
}
}
Student类需要实现Comparable接口 其次重写compareTo方法
@Override
public int compareTo(Object o) {
Student student=(Student) o;
if(this.age>student.age){
return 1;
}
if(this.age<student.age){
return -1;
}
return 0;
}
在创建TreeSet时 为其指定排序得规则
TreeSet treeSet=new TreeSet(); 但是在创建对象时 并没有为
其指定排序得规则,那么就要求该集合得元素有排序规则。 如果元素得类
已经创建完成,不能修改该类得源码,这时我们又想把该类得对象放入得
TreeSet容器中。 这时就需要你在创建TreeSet时指定排序得规则。
public class MyComparator implements Comparator {
//需要比对得两个对象
@Override
public int compare(Object o1, Object o2) {
Student s1= (Student) o1;
Student s2= (Student) o2;
if(s1.getAge()>s2.getAge()){
return 1;
}else if(s1.getAge()<s2.getAge()){
return -1;
}else {
return 0;
}
}
}
public class Demo01 {
public static void main(String[] args) {
//Comparator<? super E> comparator
//为TreeSet容器指定了排序规则
TreeSet treeSet=new TreeSet(new
MyComparator());
treeSet.add(new Student(18,"王亚波"));
treeSet.add(new Student(17,"潘世浩"));
treeSet.add(new Student(19,"刘晓东"));
treeSet.add(new Student(19,"娄明阳"));
System.out.println(treeSet);
}
}
5.Map 属于键值对模式
map中得每个元素属于键值对模式。 如果往map中添加元素时 需要添加key
和 value. 它也属于一个接口,该接口常见得实现类有: HashMap.
(1)如何创建Map对象
//默认初始化大小为16 负载因子为0.75
Map map=new HashMap();
//初始化大小
Map map2=new HashMap(16);
//初始化大小 负载因子
Map map3=new HashMap(16,0.78f);
(2)添加操作
//默认初始化大小为16 负载因子为0.75
Map map=new HashMap();
//添加操作 key: name value: 高景霞
map.put("name","高景霞"); //注意: 要求map得key必
须唯一。
map.put("age",18);
map.put("name","李赛"); //因为key不能重复,所以后
者会把前者覆盖
Map m1=new HashMap();
m1.put("k1","v1");
m1.put("k2","v2");
map.putAll(m1); //把m1中得每个元素 添加到map中
map.putIfAbsent("age",28) ;//如果指定得key存在,
则不放入map中,如果不存在则放入map中
System.out.println(map);
(3)删除操作
//删除操作
map.remove("age2");//根据指定得key移除元素
System.out.println(map);
map.clear(); //清空map容器
System.out.println(map);
(4)修改操作
//修改操作
map.replace("name","张杰");//替换元素
System.out.println(map);
(5)查询
public static void main(String[] args) {
Map map=new HashMap();
map.put("k1","v1");
map.put("k4","v4");
map.put("k2","v2");
map.put("k3","v3");
//查询操作
boolean f = map.containsKey("k5");//判断map是否
存在指定得key
Object v = map.get("k5"); //根据指定的key获取对应
得value值
System.out.println(v);
Set keys = map.keySet();//返回该map中所有得key
System.out.println(keys);
//遍历map.
for(Object k:keys){
Object value= map.get(k);//
System.out.println(k+"================>"+value);
}
}
6.泛型
(1)什么是泛型
泛型就是限制我们得数据类型。
语法:
Plain Text
List<E>:E类型约束
Set<E> : E类型约束
Map<K,V>:K,V类型约束
(2)为什么使用泛型?
我们原来在定义集合时,是如下得定义方式:
public static void main(String[] args) {
List<String> list=new ArrayList<>();//这里就限制
了集合中每个元素得类型。
list.add("java01");
list.add("hello"); //因为集合中只能添加String类型
list.add("world"); //因为集合中只能添加String类型
String s = list.get(0); //在获取元素时 默认就是相应
得数据类型 而无需在进行转换
//<K,V>:K:表示键得泛型 V:表示值得泛型
HashMap<String,Integer> map=new HashMap<>();
map.put("name",15);
map.put("age",25);
Set<String> keys = map.keySet();
}
(3)如何使用泛型
List<类型> list=new ArrayList<类型>(); 只能在该集合中存储指定得类型
public static void main(String[] args) {
List<String> list=new ArrayList<>();//这里就限制
了集合中每个元素得类型。
list.add("java01");
list.add("hello"); //因为集合中只能添加String类型
list.add("world"); //因为集合中只能添加String类型
String s = list.get(0); //在获取元素时 默认就是相应
得数据类型 而无需在进行转换
//<K,V>:K:表示键得泛型 V:表示值得泛型
HashMap<String,Integer> map=new HashMap<>();
map.put("name",15);
map.put("age",25);
Set<String> keys = map.keySet();
}
(4)能否自己定义泛型:可以
public class 类名<标识,标识....> {
标识 变量名;
public 标识 方法名(){
}
public void 方法名(标识 参数名){
}
.........
}
定义坐标类
public class Test03 {
public static void main(String[] args) {
//在创建泛型类对象时没有指定相应得泛型类型。则默认为
Object类型
Point p1=new Point();
p1.setX(15);
p1.setX("北纬50度");
//这里得泛型必须都是对象类型
Point<Integer> p2=new Point<Integer>() ;
p2.setX(25);
p2.setY(65);
Integer x = p2.getX();
Integer y = p2.getY();
p2.show();
Point<String> p3=new Point<>();
}
}
class Point<T>{
private T x;
private T y;
public void show(){
System.out.println("x坐标为:"+x+";y坐标为:"+y);
}
public T getX() {
return x;
}
public void setX(T x) {
this.x = x;
}
public T getY() {
return y;
}
public void setY(T y) {
this.y = y;
}
}