集合框架
第一部分
1、数据、对象和集合
面向对象操作的是对象,数据多了需要进行封装,封装成了对象,对象多了也需要存储,对象多了用集合存储;
2、数组和集合的区别
数组:长度是固定的,存的对象只能是同一个类型的;集合:可变长度,只要是对象都可以存储;3、集合框架
|--集合框架的构成以分类
Collection|--List|--ArrayList|--LinkedList|--Vector|--Set
|--HashSet|--TreeSet
|--容器之间的区别
这些容器对数据的存储方式不同,这种存储方式称之为:数据结构;
|--集合框架的共性方法
|--add方法的参数类型是Object,以便接收任意类型的对象;
|--集合中存储的都是对象的引用;
|--Collection 接口 //里面的共性方法,基本的操作
boolean add(E e) 添加元素
void clear() 清空集合
boolean remove(Object o) 删除元素
int size() 获取个数,集合长度
boolean contains(Object o) 判断元素是否包含
boolean isEmpty() 判断集合是否为空
boolean retainAll(Collection<?> c) 取两个集合的交集
4、迭代器
概念:就是集合的取出元素的方式;
特点:每个容器里面都有存和取的方式,因为每个容器的数据结构不同,所以它们存取的动作不一样,具体的实现方式也是不同的;就是把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素,那么取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以取出的动作细节也是不一样的,但是都有共性内容,这个共性内容就是判断和取出,那么可以将这些共性抽取出来,就是Iterator接口;那么这些内部类都符合一个规则,该规则就是Iterator,如何获取集合的取出对象?通过一个对外提供的方法就是iterator();-->取出方式;
Iterator接口
|-- Iterator<E> iterator()
|--boolean hasNext() 如果仍有元素可以迭代,则返回 true。
|--E next() 获取下一个元素
|--Iterator it = al.iterator();获取迭代器,用于取出集合中的元素
|--接口型引用只能指向自己的子类对象,而这个对象不是new出来的,而是通过collection集合里面的方法获取到的;
5、List集合
特点:元素是有序的,元素是可以重复的;因为该集合体系有索引;只有List集合里面的元素具备增删改查List集合特有方法:凡是带有角标操作的都是List集合的特有方法;
|--ListIterator<E> listIterator() List 集合特有的迭代器|--E set(int index, E element) 只有 List 集合具备:可以改变角标位置上的元素|--List<E> subList(int fromIndex, int toIndex) 包含头不包含尾|--int indexOf(Object o) 通过indexOf获取对象的位置
|--int lastIndexOf(Object o)6、ListIterator
|--ListIterator:列表迭代器-->ListIterator继承了Iterator ,列表迭代器里面的方法比迭代器里面的方法要多;|--List集合特有的迭代器,ListIterator是Iterator 的子接口,在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常,所以,在迭代时,只能用迭代器的方法操作元素。可是Iterator 方法是有限的,只能对元素进行判断,取出和删除操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator,该接口只能通过List集合的ListIterator方法获取;|--需求:想要对集合中的元素取出,在取出的过程中,想做一些操作,如在迭代过程中想要添加或者是删除元素;
问题:如果这时使用的是Iterator迭代器的话,那么会引发并发修改异常:ConcurrentModificationException,意思是说:不能做的是对一组元素,进行多种操作,不能即用集合,又用迭代器操作同一组元素,这样有可能会引发并发修改异常;你在取出元素,我早向里面添加元素,那么你到底要不要取元素?不清楚。
解决:要么就都使用集合的方法,要么就都使用迭代器的方法7、ListIterator代码体现
import java.util.*; class ListDemo { public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java1"); al.add("java2"); al.add("java3"); al.add("java4"); sop(al); ListIterator li = al.listIterator(); while(li.hasNext()) { Object obj = li.next(); // 在迭代的过程中,判断元素,并操作元素 if(obj.equals("java2")) // li.add("java009");//在遍历的过程中添加了新的元素 li.set("java007");//在遍历的过程中修改元素 } sop(al); /* ListIterator li = al.listIterator();//因为add是ListIterator里面特有的方法。所以不好用父类Iterator while(li.hasNext()) { Object obj = li.next(); if(obj.equals("java2")) li.add("java009"); } sop(al); Iterator it = al.iterator(); while(it.hasNext()) { Object obj = it.next(); if(obj.equals("java2")) // al.add("java008");//不能用集合的方法了。只能用迭代器的方法。 it.remove(); sop("obj="+obj); } sop(al); */ } public static void sop(Object obj) { System.out.println(obj); } }8、运行结果
9、Llst集合集体对象特点
Collection
|--List:元素是有序的,元素可以重复,因为该集合体系是有索引的;
|--ArrayList:底层的数据结构使用的是数组结构,特点:查询速度块,但是增删稍慢;线程不同步的;|--LinkedList:底层使用的是链表数据结构,特点速度很快,查询稍慢;|--Verctor:底层是数组数据结构,元老级的,同步的,什么都慢;ArrayList默认的长度是10,当超过了长度10以后,那么就要new一个新的数组,长度为50%的延长,就是15了,然后把原来的元素copy到新的数组里面来
Verctor:默认的长度是10,它是100%的延长,就是变成了20;
相比之下,ArrayList比较好一点;比较节约空间;
10、Verctor
|--枚举就是Verctor特有的取出方式,发现枚举和迭代器很像,其实枚举和迭代是一样的,|--ArrayList和Verctor的区别:Verctor支持枚举,而ArrayList没有;
11、LinkedList
链表列表实现LinkedList的特有方法:
|--void addFirst(E e)
|--addFirst 添加在头部
----java04java03java02java01----
|--void addLast(E e)
|--addLast 添加在尾部
----java01java02java03java04get方法是获取元素,但不删除元素----
|--E getFirst()|--E getLast()
remove方法是获取元素,但是元素被删除
|--E removeFirst() :是从java01开始remove|--E removeLast():是从java04开始remove
----
java04
java03
java02
java01
----
12、LinkedList模拟队列和堆栈数据结构
代码体现<span style="font-family:SimSun;font-size:14px;">/* 使用LinkedList摸以一个堆栈或者队列数据结构; 堆栈:先进后出 如同一个杯子; 队列:先进先出 如同一个水管; 面试的要求是:得把LinkedList给封装到我描述的堆栈或者队列类当中, 隐藏起来,对外暴露更简单的操作 */ import java.util.*; class DuiLie { private LinkedList link; // 一初始化就有了一个link,单独封装一下 DuiLie() { link = new LinkedList(); } // 添加元素,封装起来,自己能够识别的方法 public void myAdd(Object obj) { link.addFirst(obj); } // 取出元素,封装起来,自己能够识别的方法 public Object myGet() { // return link.removeFirst();//这个是堆栈,先进后出 return link.removeLast();//这个顺序是队列,先进先出 } // 判断是否是null,封装起来了 public boolean isNull() { return link.isEmpty(); } } class LinkedListTest { public static void main(String[] args) { // 我自己的容器,只是我的容器基于链表容器; DuiLie dl = new DuiLie(); dl.myAdd("java01"); dl.myAdd("java02"); dl.myAdd("java03"); dl.myAdd("java04"); while(!dl.isNull()) { sop(dl.myGet()); } } public static void sop(Object obj) { System.out.println(obj); } }</span>13、ArrayList练习1
取出重复元素
/* 去除ArrayList集合中的重复元素 定义一个功能,把重复元素去除, 定义一个容器,判断这个新的容器里面有没有元素1,没有的话就存进去, 新容器里面有没有1,有的话就不要,依次判断有没有2,走完以后,新的容器里面的元素就是唯一的; */ import java.util.*; class ArrayListTest { public static void sop(Object obj) { System.out.println(obj); } // 返回值类型是ArrayList 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 // 不包含就往里面存; newAl.add(obj); } return newAl; } public static void main(String[] args) { ArrayList al = new ArrayList(); al.add("java01"); al.add("java02"); al.add("java03"); al.add("java02"); al.add("java04"); al.add("java03"); al.add("java02"); // 打印原集合 sop(al); al = singleElement(al); // 打印新的集合 sop(al); } }14、ArrayList练习2
/* 将自定义对象作为元素存到ArrayList集合中,并去除重复元素, 比如:存人对象,同姓名同年龄,视为同一个人,为相同元素; 思路: 1、对人进行描述,将数据封装进人对象; 2、定义容器,将人存入; 3、取出 这边的判断元素是否相同用的是contains方法,包含,而contains的底层原理就是equals; List集合判断元素是否相同,依据的是元素的equals方法; */ import java.util.*; //而这个Person里面也是有equals方法的,因为Person本身继承Object,但是这个equals方法比较的是地址值; //而我的这个6个地址值都是不相同的 class Person { private String name; private int age; //下面的两个equals是不同的,一个是覆盖的Object里面的equals方法,一个是字符串姓名内容的比较。 // 需要重新equals,判断的是姓名和年龄 public boolean equals(Object obj)//这个equals是Person类里面的方法 { // 判断是不是Person类,而不是Demo if(!(obj instanceof Person)) return false; // 强转 Person p = (Person)obj; System.out.println(this.name+"......"+p.name); return this.name.equals(p.name) && this.age==p.age;//这个equals是判断字符串是否相同的方法 } /**/ Person(String name,int age) { this.name = name; this.age = age; } // 获取 public String getName() { return name; } public int getAge() { return age; } } class ArrayListTest2 { public static void main(String[] args) { // ArrayList判断的是对象是否相同,用的是equals,而所有的对象都是相同的 // ArrayList里面判断元素是否相同用的是equals方法; // 返回来的是true就是相同,返回为false就是不相同 ArrayList al = new ArrayList(); al.add(new Person("zhangsan01",30));//Object obj = new Person("zhangsan",30) 多态 al.add(new Person("zhangsan02",33)); al.add(new Person("zhangsan02",33)); al.add(new Person("zhangsan03",35)); al.add(new Person("zhangsan05",37)); al.add(new Person("zhangsan05",37)); al = singleElement(al); // 想要删除一个元素,那么就要拿着这个元素到集合里面去找,怎么去找就是用的equals; // sop("remove 03:"+al.remove(new Person("zhangsan05",37))); Iterator it = al.iterator(); while(it.hasNext()) { // Object obj = it.next();//it.next()返回来的是obj // Person p = (Person)obj;//想要访问子类的特有的方法的时候需要向下转型。 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;调用一次contains,contains就调用一次equals newAl.add(obj); } return newAl; } public static void sop(Object obj) { System.out.println(obj); } }15、运行的结果
第二部分
1、Set集合
|--特点:Set集合:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复;(有序:如何存进去的,就如何取出来)|--发现Set集合的方法和Collection集合是一致的;|--Set
|--HashSet:底层数据结构是哈希表;哈希表是按照哈希值来存的;
|--HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成,如果元素的hashCode值相同,才会判断equals是否为true如果元素的hashCode值不同,不会调用equals;
2、哈希值
import java.util.*; class HashSetDemo { public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); sop(d1); sop(d2); } public static void sop(Object obj) { System.out.println(obj); } } class Demo { }3、哈希值
|--在哈希表里面,当哈希值重复的时候,还有一次校验方式,就是我们的元素的对象是不是相同的;判断是否是同一个对象用的是equals方法;|--如果判断到的哈希值的地址值是一样的,那么就判断是否是同一个对象,如果不是,那么就在该地址值下顺延;都在同一个地址值上;
|--哈希表结构的特点:先看哈希值,如果哈希值是一样的,在比较砸门是不是同一个对象,用equals比较;
4、HashSet练习
<p><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">/*</span></p><p>往hashSet集合中存入自定义对象 姓名和年龄视为同一个人,重复元素;</p> 定义一个对象通常要复写hashCode和equals,因为有可能你的对象要存到HashSet集合中; */ import java.util.*; class HashSetTest { public static void main(String[] args) { HashSet hs = new HashSet(); // 下面这些元素都有自己的哈希值, hs.add(new Person("a4",14)); hs.add(new Person("a1",11)); hs.add(new Person("a2",12)); hs.add(new Person("a2",12)); hs.add(new Person("a3",13)); hs.add(new Person("a4",14)); hs.add(new Person("a4",14)); hs.add(new Person("a5",15)); // sop("contains::"+hs.contains(new Person("a1",11)));//判断某个元素是否存在 // hs.remove(new Person("a2",12));//删除某个元素 Iterator it = hs.iterator(); while(it.hasNext()) { Object obj = it.next(); Person p = (Person)obj; sop(p.getName()+"::"+p.getAge()); } } public static void sop(Object obj) { System.out.println(obj); } } //描述人 class Person { private String name; private int age; // 覆盖Person的默认的hashCode方法,建立Person自己的hashCode方法; public int hashCode()//对象底层自己调用的; { // 按照姓名和年龄来生成一个哈希值; // 按照条件生成哈希值 // 字符串本身已经实现了hashCode,( String int hashCode() ) return name.hashCode()+age*26; } Person(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } //对象底层自己调用的; public boolean equals(Object obj)//这个必须要做转换,而且要进行判断是不是这种类型 { if(!(obj instanceof Person)) return false; Person p = (Person)obj; System.out.println(this.name+"......"+p.name);//如果这句话打印了,代表equals被调用了; return this.name.equals(p.name) && this.age==p.age; } }5、运行结果
第三部分
1、TreeSet
特点:TreeSet可以对Set集合中的元素进行排序;|--TreeSet集合:|--可以对Set集合中的元素进行排序,|--底层数据结构是二叉树;|--保证元素唯一性的依据:compareTo方法的return 0;|--TreeSet集合排序第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖一个compareTo,还要判断主要条件和次要条件;这种方式也称为元素的自然顺序,或者叫做默认顺序;|--TreeSet集合排序第二种方式:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要集合自身具备比较性;在集合一初始化时,就有了比较性;当两种排序都存在时,以比较器为主,定义一个类,实现Comparator接口,覆盖compare方法;2、TreeSet第一种排序方式练习
/* 往TreeSet集合中存储自定义对象学生 想按照学生的年龄进行排序; */ import java.util.*; class TreeSetDemo { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new Student("lisi005",24)); ts.add(new Student("lisi008",20)); ts.add(new Student("lisi007",22)); ts.add(new Student("lisi007",22)); ts.add(new Student("lisi004",22)); // ts.add(new Student("lisi54",26)); Iterator it = ts.iterator(); while(it.hasNext()) { // Object obj = it.next(); // Student stu = (Student)obj; Student stu = (Student)it.next(); sop(stu.getName()+"::"+stu.getAge()); } } public static void sop(Object obj) { System.out.println(obj); } } //Comparable该接口强制让学生具备比较性 class Student implements Comparable { private String name; private int age; // 返回的是一个int型的数据;需要传一个对象进来; public int compareTo(Object obj) { // return 1;//怎么存进去的,就怎么取出来。 // return -1;//反着取出元素 // return 0;//元素都是相同的 /* 按照年龄和姓名进行排序。*/ if(!(obj instanceof Student)) throw new RuntimeException("此对象不是学生");//抛出的是RuntimeException异常,不是Exception异常 Student s =(Student)obj;//如果是学生的话,就强转 System.out.println(this.name+"..compareto.."+s.name); if(this.age<s.age) return 1; // 当主要条件相同,就要判断次要条件; // 当年龄相等时,就要比较姓名 // int compareTo(String anotherString) if(this.age==s.age) return this.name.compareTo(s.name); return -1; } Student(String name,int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }3、运行结果
4、TreeSet第二种排序方式练习
/* 练习:按照字符串长度排序 字符串本身具备比较性,但是它的比较方式不是所需要的 这时就只能使用比较器 */ import java.util.*; class TreeSetTest { public static void main(String[] args) { TreeSet ts = new TreeSet(new StrLenCompartor()); ts.add("thwht"); ts.add("aef"); ts.add("aaa"); ts.add("jy"); ts.add("shda"); ts.add("yjet"); Iterator it = ts.iterator(); while(it.hasNext()) { sop(it.next()); } } public static void sop(Object obj) { System.out.println(obj); } } //类实现Comparator接口 class StrLenCompartor implements Comparator { public int compare(Object o1,Object o2) { // 强转 String s1 =(String)o1; String s2 =(String)o2; int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); // 判断次要条件 if(num==0) return s1.compareTo(s2); return num; /**/ /* if(s1.length()>s2.length()) return 1; else if(s1.length()==s2.length())//主要条件判断如果相同,再判断次要条件, return s1.compareTo(s2);//次要条件的判断是通过字符串的compareTo方法。 return -1; */ } }5、运行结果
第四部分
我的总结
|--LinkedList集合里面有addFirst ,addLast方法,可以总结为addFirst 开始为尾部,addLast开始为头部;|--removeFirst:是从java01开始remove;|--removeLast:是从java04开始remove;|--List集合判断元素是否相同,依据的是元素的equals方法;|--在ArrayList或者LinkedList的remove和contains底层用的是equals方法;|--HashSet集合对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法;|--哈希表结构的特点:先看哈希值,如果哈希值是一样的,在比较砸门是不是同一个对象,用equals比较;|--TreeSet集合:排序时,当主要条件相同时,一定要判断一下次要条件;|--TreeSet集合:想要判断元素是否包含,或者删除元素,走的都是compareTo方法,走的是return 0;|--TreeSet集合:两种排序:一个是让元素自身具备比较性,一个是让容器自身具备比较性,如果都具备了,以比较器为主;
本文详细介绍了Java集合框架的基础知识,包括集合、数组与集合的区别、集合框架的构成与分类,以及List、Set等常见集合的特性与使用方法。重点讲解了List集合的特性与特有方法、迭代器的使用,HashSet如何保证元素唯一性,TreeSet如何实现排序。




5418

被折叠的 条评论
为什么被折叠?



