集合框架————————java视频
来源:互联网 发布:redis hash key mysql 编辑:程序博客网 时间:2024/06/01 13:28
集合(java.util包中)又称为容器,数据在内存中存储方式称为数据结构,各自自身的特点不同,每一个容器对数据的存储方式不同,所以就出现了多钟容器,对多种进行共性抽取(不断向上抽取的往往是抽象的),即产生体系,称为集合框架。集合框架是用来表现和操纵集合的一个统一的体系结构。
抽取到顶层即collection,定义体系的最基本、最共性的功能。而使用一般是选择底层,因为1、顶层的抽象不能创建对象。2、创建子类对象的方法更多。看顶层基本共性,参阅底层创建对象。
共性方法:
1、add方法的参数是object,以便于接受任意类型的对象
2、集合中存储的都是对象的引用(地址)
迭代器:
迭代器就是集合的取出元素的方式,对于取出这个动作不足以用一个函数描述,需要用多个功能来体现,一般情况下,把多个功能封装到对象中去。每一个容器(如Set、List)都存在一个取出的对象(内部类操作集合中的元素更加方便),数据结构不同,每一个对象中取出的实现不用,但都有共性的内容,即判断和取出,将共性抽取形成了接口Iterator。
通过对外提供的方法iterator()获取集合的取出对象。
常见子接口
List集合:元素是有序的,元素可以重复。该集合体系有索引。
特有方法:凡是可以操作角标的方法
指定位置插入元素,可以通过索引获取,可以判断元素的位置,根据位置获取某一个元素,list集合特有的迭代器。可以改变一个位置的元素。
增
add(index,element);
addAll(index,Collection);
删
remove(index);
修改元素
set(index,element);
通过角标获取元素
get(index);
subList(from,to);包含from,不包括to
listIterator();
List集合特有的迭代器,ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,会发生并发修改异常,迭代过程中只能使用迭代器方法操作元素,可是Iterator方法是有限的,如果想要其他操作如添加,修改,就需要使用子接口,ListIterator。该接口只能通过List集合的listIterator方法获取。 List集合判断元素是否相同时(contains和remove),依据的是元素的equals方法(比较的都是地址)。
List中常见三个子对象(底层数据结构不一样)
1、ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,增加删除比较麻烦。线程不同步。不断new数组产生可变长度数组。超过其默认创建数组长度(10)就开始百分之五十延长。
举例:去除ArrayListTest集合中的重复元素。
import java.util.*;class ArrayListTest{ public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java01"); al.add("java02"); al.add("java01"); al.add("java02"); sop(al); al = singleElement(al); sop(al); } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newAl.contains(obj)) newAl.add(obj); } return newAl; } public static void sop(Object obj) { System.out.println(obj); }}
举例2:将自定义对象作为元素存到ArrayList集合中,并且去除重复元素
比如:存人对象,同姓名,同年龄的视为同一个人,为重复元素。
思路:
1、对人描述,将数据封装进人对象
2、定义容器,将人存入
3、取出
class Person{ private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } public boolean equals(Object obj) { if(!(obj instanceof Person)) return false; Person p = (Person)obj; return this.name.equals(p.name)&&this.age ==p.age; //这里的equals是字符串(name)的equals方法 } public String getName() { return name; } public int getAge() { return age; }}class ArrayListTest2{ public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { ArrayList al = new ArrayList(); /*ArrayList容器中判断相同的条件是使用了equals,只判断存入的对象(Person)是否相同,new Person中默认来自Object,而Object中equals判断对象相同不相同使用的是地址,所以这里的对象的地址都不同,即无法删除相同元素,按照我们的方法比较,重写equals*/ al.add(new Person("lisi01",30)); //存对象 al.add(object obj) al.add(new Person("lisi02",34)); al.add(new Person("lisi03",33)); al.add(new Person("lisi02",34)); al.add(new Person("lisi03",33)); al = singleElement(al); Iterator it = al.iterator(); while(it.hasNext()) { //sop(it.next().getName()+"::"+it.next().getAge()); /*getName不是Object(存对象时存入Object,迭代器不知道里面装的是什么元素,所以往回返的都是Object,it.next()往回返的时候返回的是Object)的方法,更改如下,用子对象特有方法时,向下转型*/ Person p = (Person)it.next(); sop(p.getName()+"::"+p.getAge()); } } public static ArrayList singleElement(ArrayList al) { //定义一个临时容器 ArrayList newAl = new ArrayList(); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(!newAl.contains(obj)) //contains调用equals方法,remove方法的底层调用的也是equals,所以重写equals时,对比的还是地址。 newAl.add(obj); }}
2、LinkedList:底层使用的是链表数据结构。查询非常慢,但是增删方便
LinkedList特有方法:
addFirst();(1.6版本中变成了offerFirst())
addLast();(1.6版本中变成了offerLast())
getFirst();(1.6版本中变成了peekFirst())
getLast();(1.6版本中变成peekLast();在这个函数中,如果列表为空,返回null,但是getLast()中如果列表为空则返回没有这个元素的异常。即NoSuchElementException)
get方法,获取元素但是不删除元素,remove也可以获取元素但是元素被删除。
removeFirst();(1.6版本中变成pollFirst();集合中没有元素返回null)
removeLast();(1.6版本中变成pollLast();)
举例:使用LinkedList模拟一个堆栈或者队列数据结构
堆栈:先进后出,如同一个杯子
队列:先进先出,如同一个水管
/*为什么要封装?直接用LinkedList是可以完成的,但是它只有自身含义,我们想做成与项目相关的容器,起一些特定的名称来用,更加方便。这个时候把原有的集合封装进我们的描述当中,并对外提供一个自己更加清楚、更能识别的名称。*/import java.util.*;class Queue{ private LinkedList link; Queue() { link = new LinkedList(); } public void myAdd(Object obj) { link.addFirst(obj); } public Object myGet() { return link.removeLast(); } public boolean isNull() { return link.isEmpty(); }}class LinkedListTest{ public static void main(String[] args) { Queue d1 = new Queue(); d1.myAdd("java01"); d1.myAdd("java02"); d1.myAdd("java03"); while(!d1.isNull()) { System.out.println(d1.myGet()); } }}//更改myGet中的removeLast为removeFirst则为堆栈,即先进后出
3、 Vector:底层是书序数据结构,Vector比ArrayList出现的早,线程同步,被ArrayList替代了,增删与查询都慢。不断new数组产生可变长度数组。超过其默认创建数组长度(10)就开始百分之百延长。枚举是Vector特有的取出方式,发现枚举和迭代器很像,其实是一样的,由于枚举的名称以及方法的名称都过长,所以被迭代器取代了,枚举郁郁而终了。
假使元素中涉及到挺多的增删,那么就考虑使用LinkedList,如果涉及增删不频繁,那么可以使用ArrayList和LinkedList,如果涉及增删也涉及查询,那么选用ArrayList,频繁的增删不多见。
Set集合:元素是无序的(存入和取出的顺序不一定一致,有序是怎么存入,怎么取出),元素不可重复。
Set集合的功能呢和Collection是一致的。
重点关注子类对象,常见的子类:HashSet(线程非同步的。底层数据结构是哈希表:保证集合不重复的依据是HashCode值是否相同,相同则继续判断equals方法是否为真)和TreeSet(可以对Set集合中的元素进行排序)
Hash表:Hash值一样再比较对象是否一样,不是同一个对象
,这个时候会在该地址下顺延。同一个地址,同一个对象时,则不存,即元素不可重复。Hash值不同,直接另存。
往hashset集合中存入自定义对象,姓名和年龄相同都为同一个人,重复元素。
import java.util.*;class HashSetTest{ public static void sop(Object obj) { System.out.println(obj); } public static void main(String[] args) { HashSet hs = new HashSet(); hs.add(new Person("a1",11)); hs.add(new Person("a2",4)); hs.add(new Person("a3",21)); hs.add(new Person("a4",13)); /*四个独立的new建立了四个新的地址,对应为其hash值,重新建立Person对象自己的hash值(复写hashCode),依据判断条件生成hash值*/ Iterator it = hs.iterator(); sop("a1:"+hs.contains(new Person("a2",4))); hs.remove(new Person("a3",21)) while(it.hasNext()) { Person p = (Person)it.next(); sop(p.getName()+"::"+p.getAge()); } }}class Person{ private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } public int hashCode() { System.out.println(this.name+"……hashcode"); //帮助查看hash值什么时候调用//return 60; /*生成Hash值,equals运行,所有hash值都是60,所以在地址上依次比较对象内容,不相同的时候,在原位置下,顺延地址往下存。每一个hash值一样,这样是不合适的,按照条件设定hash值*/ return name.hashCode()+age; //字符串本身有hashCode的方法,为保证Hash值唯一,可以将年龄乘上某一个数据 } public String getName() { return name; } public int getAge() { return age; } public boolean equals(Object obj) { if(!(obj isntanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"……equals……"+p.name); return this.name.equals(p.name)&&this.age ==p.age; //这里的equals是字符串(name)的equals方法 }}
HashSet如何保证元素的唯一性的?是通过元素的两个方法,hashcode和equals来完成的。如果元素的hashCode值相同,才会判断equals是否为true,如果元素的hashcode不同,才会调用equals
当自已定义对象时,要复写hashCode和equals,注意复写函数的时候不要把函数名和参数写错。对于判断元素是否存在,添加或者删除等操作,依赖的方法是元素的hashCode和equals方法,先判断hashCode,如果有,则判断equals。有可能对象要存放到HashSet中,如果不复写hashCode,那么存放的hashCode都依据地址来判断,如果都是new出来的对象,地址自然不同,那么就不会判断对象内容。hashCode和equals不是自己调用的,是底层调用。查看调用过程可以通过输出语句来看看。
TreeSet:TreeSet集合可以排序,但是你没有指定按照什么方式排序的时候,元素具备比较性才能排序,TreeSet的要求是存的对象必须具备比较性,如何具备比较性?实现接口Comparable(预先使用接口中的方法),只要实现接口就具备了比较性。Comparable接口强行对实现它的类的对象整体排序,这种排序称为类的自然排序。类的comparaTo方法被称为它的自然比较方法。复写compareTo函数,此函数判断比较的主要条件和次要条件记住,排序时,当主要条件相同时,一定要判断一下次要条件。
TreeSet底层的数据结构:二叉树,也叫红黑树,元素多的时候取中间值,方便比较大小。保证元素唯一性的依据是compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法,也称为元素的自然顺序,或者叫做默认顺序。元素一定义完,自身具有比较性。
TreeSet的第二种排序方式,当元素自身不具备比较性时,或者具备比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。即参与构造方法,定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。定义一个类,实现Comparator接口,覆盖compare方法。
- java集合——集合框架
- <java——集合框架>
- Java——集合框架
- java集合框架—List
- Java基础—集合框架
- Java集合框架—Set
- Java集合框架—Map
- Java集合框架—List
- Java学习—集合框架
- JAVASE—java集合框架
- 《Java专栏》— 集合框架
- Java集合框架——集合框架概况
- 集合框架————————java视频
- 集合框架—ArrayList集合
- 集合框架—Map集合
- 集合框架—泛型
- 集合框架—Set
- Foundation框架—集合
- Math——HDUOJ 1290
- SpringMvc中关于@ResponseBody和HashMap的用法
- 【最小环 && 离散化】HDU 6005 Pandaland
- HPUACM Freshman Exercises Round 1 [标程]
- 【Android studio】为按钮添加简单事件
- 集合框架————————java视频
- ACM-11月12日周日周末训练心得
- Reversing Linked List
- L
- Mysql基础学习笔记
- 【考研】第十一周总结
- AtomicInteger的认识与使用
- Python---内置方法
- 习题4.3(2)