黑马程序员——Java中的集合(上)
2015-10-19 16:04
459 查看
——- android培训、java培训、期待与您交流! ———-
集合特点:
用于存储对象的容器。
集合的长度是可变的。
集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。
Java集合类主要由两个接口(Collection和Map)派生出来:
Collection
List(子接口):有序(存入和取出的顺序一致),可以重复,有索引
Vector(实现类):
底层数据结构:数组
线程:同步
操作数据:增删,查询都很慢
Enumeration elements()
返回此向量的组件的枚举。
IO流中SequenceInputStream中用到
e.g.
Vector v = new Vector;
Enumeration en =v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
ArrayList(实现类): 替代了Vector
底层数据结构:数组
线程:不同步
操作数据:增删稍慢、改查很快
LinkedList(实现类):
底层数据结构:链表
线程:不同步
操作数据:增删除很快,改查很慢
Set(子接口) :无序(存入和取出的顺序不一定一致),不能重复
HashSet(实现类):底层数据结构是哈希表,不同步
LinkedHashSet:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现
TreeSet(实现类):底层数据结构是二叉树,不同步,可以对Set集合中的元素进行排序
Map:存储键值对,一次添加一对,而且要保证键的唯一性
Hashtable实现类):
底层数据结构:哈希表,不可以存入null键null值
线程:同步
操作数据:jdk1.0.效率低
HashMap实现类):
底层数据结构:哈希表,允许使用 null值和null键
线程:不同步
操作数据:将hashtable替代,jdk1.2.效率高
TreeMap实现类):
底层数据结构:二叉树
线程:不同步
操作数据:用于给map集合中的键进行排序
添加:
boolean add(Object obj);
boolean addAll(Collection coll);
删除:
boolean remove(Object obj);
boolean removeAll(Collection coll);
void clear( );
判断:
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();判断集合中是否有元素。
获取:
int size( );
Iterator iterator( );
其他:
boolean retainAll(Collection coll); 取交集
Object toArray( ); 将集合转成数组
对所有的Collection容器进行元素取出的公共接口,称为迭代器
Collection中有iterator方法,所以每一个子类集合对象都具备迭代器
它替代了Vector类中的Enumeration(枚举)。迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
方法:
boolean hasNext():若被迭代的集合元素还没有被遍历,返回true.
Object next():返回集合的下一个元素.
void remove():删除集合上一次next()方法返回的元素。(若集合中有多个相同的元素,都可以删掉)
取出集合的元素代码示例:
子接口:
ListIterator:专门输出List中的元素
方法:
boolean hasNext()
E next() 返回列表中的下一个元素。
int nextIndex()
void add(E e) 将指定的元素插入列表(可选操作)
void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
E previous()返回列表中的前一个元素。
添加
void add(index,element);
void addAll(index,collection);
删除
Object remove(index);
boolean remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
修改
Object set(index,element);
获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object):
List subList(from,to);
list特有的取出元素的方式之一
for(int x = 0; x < list.size(); x++){
System.out.println( “get:” + list.get(x));
}
List集合特有的迭代器:ListIterator(列表迭代器)
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常;
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出和删除的操作;
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator.该接口只能通过List集合的listIterator方法获取 。
void addFirst(); 1.6以后版本为offerFirst( )
void addLast(); 1.6以后版本为offerLast( )
E getFirst();获取但不移除,如果链表为空,抛出NoSuchElementException。
1.6以后版本为:peekFirst(); 获取但不移除,如果链表为空,返回null
E getLast(); 1.6以后版本为:peekLast( );
E removeFirst(); 获取并移除,如果链表为空,抛出NoSuchElementException。
1.6以后版本为:pollFirst( );获取并移除,如果链表为空,返回null
E removeLast(); 1.6以后版本为: pollLast( );
内部数据结构是哈希表,是不同步的。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,haseCode和equals来完成的。
如果元素的HashCode值相同,才会判断equals是否为true;
如果元素的HashCode值不同,不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
代码示例:
运行结果:
LinkedHashSet
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,该类为HashSet的子类,可以将无序变有序。
可以对Set集合中的元素进行排序(字母的自然顺序),底层数据结构是二叉树
判断元素唯一性的方式:就是根据保证元素唯一性的依据比较方法(实现Comparable接口中根据覆盖的compareTo方法返回值,实现Comparator接口中根据覆盖的compare方法)的返回结果是否是0,是0,就是相同元素,不存。
排序:
排序:
第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。
Comparable接口:位于java.lang包中,只有一个方法compareTo
int compareTo(T o):比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
代码示例:
运行结果:
第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,就让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
注意:如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器的比较规则为准
代码示例:
运行结果:
一、集合类
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进行存储,集合就是存储对象最常用的一种方式。集合特点:
用于存储对象的容器。
集合的长度是可变的。
集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体容器。不断的向上抽取,就形成了集合框架。
二、集合类的构成:
1. 集合框架的构成及分类
Java集合类主要由两个接口(Collection和Map)派生出来:
Collection
List(子接口):有序(存入和取出的顺序一致),可以重复,有索引
Vector(实现类):
底层数据结构:数组
线程:同步
操作数据:增删,查询都很慢
Enumeration elements()
返回此向量的组件的枚举。
IO流中SequenceInputStream中用到
e.g.
Vector v = new Vector;
Enumeration en =v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
ArrayList(实现类): 替代了Vector
底层数据结构:数组
线程:不同步
操作数据:增删稍慢、改查很快
LinkedList(实现类):
底层数据结构:链表
线程:不同步
操作数据:增删除很快,改查很慢
Set(子接口) :无序(存入和取出的顺序不一定一致),不能重复
HashSet(实现类):底层数据结构是哈希表,不同步
LinkedHashSet:具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现
TreeSet(实现类):底层数据结构是二叉树,不同步,可以对Set集合中的元素进行排序
Map:存储键值对,一次添加一对,而且要保证键的唯一性
Hashtable实现类):
底层数据结构:哈希表,不可以存入null键null值
线程:同步
操作数据:jdk1.0.效率低
HashMap实现类):
底层数据结构:哈希表,允许使用 null值和null键
线程:不同步
操作数据:将hashtable替代,jdk1.2.效率高
TreeMap实现类):
底层数据结构:二叉树
线程:不同步
操作数据:用于给map集合中的键进行排序
2. Collection接口:
Collection的常见方法:添加:
boolean add(Object obj);
boolean addAll(Collection coll);
删除:
boolean remove(Object obj);
boolean removeAll(Collection coll);
void clear( );
判断:
boolean contains(Object obj);
boolean containsAll(Collection coll);
boolean isEmpty();判断集合中是否有元素。
获取:
int size( );
Iterator iterator( );
其他:
boolean retainAll(Collection coll); 取交集
Object toArray( ); 将集合转成数组
3. Iterator接口
概述:对所有的Collection容器进行元素取出的公共接口,称为迭代器
Collection中有iterator方法,所以每一个子类集合对象都具备迭代器
它替代了Vector类中的Enumeration(枚举)。迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException。
方法:
boolean hasNext():若被迭代的集合元素还没有被遍历,返回true.
Object next():返回集合的下一个元素.
void remove():删除集合上一次next()方法返回的元素。(若集合中有多个相同的元素,都可以删掉)
取出集合的元素代码示例:
方式一: Iterator it=al.iterator();//获取迭代器,用于取出集合中的元素。 while(it.hasNext()) { System.out.println(it.next()); } //方式二:for循环结束,Iterator变量内存释放,更高效 for (Iterator it=al.iterator();it.hasNext() ; ) { System.out.println(it.next()); }
子接口:
ListIterator:专门输出List中的元素
方法:
boolean hasNext()
E next() 返回列表中的下一个元素。
int nextIndex()
void add(E e) 将指定的元素插入列表(可选操作)
void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
boolean hasPrevious() 如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
E previous()返回列表中的前一个元素。
三,List
Collection的子接口,有序(存入和取出的顺序一致),元素都有索引(角标),允许重复元素1. 特有的常见方法。
特点:都可以操作角标。添加
void add(index,element);
void addAll(index,collection);
删除
Object remove(index);
boolean remove(Object o) 从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
修改
Object set(index,element);
获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object):
List subList(from,to);
list特有的取出元素的方式之一
for(int x = 0; x < list.size(); x++){
System.out.println( “get:” + list.get(x));
}
List集合特有的迭代器:ListIterator(列表迭代器)
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常;
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出和删除的操作;
如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator.该接口只能通过List集合的listIterator方法获取 。
2. ArrayList
基本方法:增删改查,与List中的方法基本一致3. LinkedList
基本方法:void addFirst(); 1.6以后版本为offerFirst( )
void addLast(); 1.6以后版本为offerLast( )
E getFirst();获取但不移除,如果链表为空,抛出NoSuchElementException。
1.6以后版本为:peekFirst(); 获取但不移除,如果链表为空,返回null
E getLast(); 1.6以后版本为:peekLast( );
E removeFirst(); 获取并移除,如果链表为空,抛出NoSuchElementException。
1.6以后版本为:pollFirst( );获取并移除,如果链表为空,返回null
E removeLast(); 1.6以后版本为: pollLast( );
四,Set
Collection的子接口,元素不可以重复,是无序的,Set接口中的方法和Collection一致1. HashSet:
概述:内部数据结构是哈希表,是不同步的。
HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,haseCode和equals来完成的。
如果元素的HashCode值相同,才会判断equals是否为true;
如果元素的HashCode值不同,不会调用equals。
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
//HashSet集合中添加重复元素时,返回false System.out.println(hs.add("java01")); System.out.println(hs.add("java01"));//未存储进去为false
代码示例:
import java.util.HashSet; import java.util.Iterator; /* * 往HashSet集合中存入自定义对象姓名和年龄相同为同一个人,重复元素。 */ class HashSetDemo { public static void main(String[] args) { System.out.println("以下为集合中元素存储的比较过程:"); HashSet<Person> hs = new HashSet<Person>(); hs.add(new Person("a1", 11)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 13)); hs.add(new Person("a2", 12)); hs.add(new Person("a3", 14)); System.out.println("去掉重复元素后的结果:"); Iterator<Person> it = hs.iterator(); while (it.hasNext()) { Person p = it.next(); System.out.println(p.getName() + "..." + p.getAge()); } } } class Person { private String name; private int age; Person(String name, int age) { this.name = name; this.age = age; } // 复写hashCode方法,集合底层内部调用 public int hashCode() { System.out.println(this.name + "...hashCode"); return name.hashCode() + age * 3;// *3保证hash值的唯一性 } // 复写equals方法 public boolean equals(Object obj) { if (!(obj instanceof 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为Object的方法. } public String getName() { return name; } public int getAge() { return age; } }
运行结果:
LinkedHashSet
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现,该类为HashSet的子类,可以将无序变有序。
2. TreeSet
特点:可以对Set集合中的元素进行排序(字母的自然顺序),底层数据结构是二叉树
判断元素唯一性的方式:就是根据保证元素唯一性的依据比较方法(实现Comparable接口中根据覆盖的compareTo方法返回值,实现Comparator接口中根据覆盖的compare方法)的返回结果是否是0,是0,就是相同元素,不存。
排序:
排序:
第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。
Comparable接口:位于java.lang包中,只有一个方法compareTo
int compareTo(T o):比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
代码示例:
import java.util.Iterator; import java.util.TreeSet; /** * 需求: 往TreeSet集合中存储自定义对象学生。 年龄和姓名均相同时,视为同一个人, * 并按照学生的年龄进行排序, 当年龄相同时,按照名字的自然顺序排序 */ public class TreeSetDemo { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<Student>(); ts.add(new Student("C", 19)); ts.add(new Student("D", 17)); ts.add(new Student("C", 19)); ts.add(new Student("A", 20)); ts.add(new Student("E", 17)); Iterator<Student> it = ts.iterator(); while (it.hasNext()) { Student s = (Student) it.next(); System.out.println(s.getName() + "..." + s.getAge()); } } } class Student implements Comparable<Student> { // 该接口强制让学生具备比较性。 private String name; private int age; Student(String name, int age) { this.name = name; this.age = age; } public int compareTo(Student s) { // 内部底层调用 // 存与取的方式相同,将不能除去重复的对象元素 //return 1; // 存与取的方式刚好相反,将不能除去重复的对象元素 // return -1; // 按自然顺序取出 System.out.println(this.name + ":compareto:" + s.name); if (this.age > s.age) { return 1; // 判断次要条件:当年龄相同时,比较姓名是否相同 } else if (this.age == s.age) { return this.name.compareTo(s.name);// 字符串自有的比较方法。 } else return -1; /*简化书写 int temp = this.age - s.age; return temp == 0? this.name.compareTo(s.name) : temp;*/ } public String getName() { return name; } public int getAge() { return age; } }
运行结果:
第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,就让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
注意:如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器的比较规则为准
代码示例:
import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /* * 需求:按姓名排序,不修改compareTo方法 */ class TreeSetDemo2 { public static void main(String[] args) { TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());// 将比较器对象作为参数传递给TreeSet集合的构造函数 ts.add(new Student("A", 20)); ts.add(new Student("C", 19)); ts.add(new Student("E", 17)); ts.add(new Student("D", 17)); ts.add(new Student("A", 18)); ts.add(new Student("C", 19)); Iterator<Student> it = ts.iterator(); while (it.hasNext()) { Student s = (Student) it.next(); System.out.println(s.getName() + "..." + s.getAge()); } } } class Student implements Comparable<Student> { // 该接口强制让学生具备比较性。 private String name; private int age; Student(String name, int age) { this.name = name; this.age = age; } public int compareTo(Student s){ // 内部底层调用 // 按自然顺序取出 System.out.println(this.name + ":compareto:" + s.name); int temp = this.age - s.age; return temp == 0? this.name.compareTo(s.name) : temp; } public String getName() { return name; } public int getAge() { return age; } } // 定义一个类,实现Comparator接口 class MyCompare implements Comparator<Student> { //覆盖compare方法 public int compare(Student s1, Student s2) { int num = s1.getName().compareTo(s2.getName()); if (num == 0) { /*//第一种方法 if(s1.getAge()>s2.getAge()) return 1; if(s1.getAge()==s2.getAge()) return 0; return -1; */ /*//第二种方法 return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));*/ // 第三种方法 return s1.getAge() - s2.getAge(); } return num; } }
运行结果:
相关文章推荐
- 专访雷果国:从1.5K到18K 一个程序员的5年成长之路
- 黑马程序员——java基础---IO---字符流
- 2015年网易公司校招笔试编程+3轮面试
- 黑马程序员——Java 权限public、protected、private、default
- iOS 面试题汇总
- 程序员久坐不动的8大危害
- J2EE面试题
- 【.Net码农】SWFUpload 在IE9下不显示问题及IE9中模态窗下flash文件选择问题的处理
- 黑马程序员——Java设计模式
- 黑马程序员——Java多线程
- 2015年腾讯暑期实习面试总结(技术岗)
- 分享8年开发经验,浅谈java程序员职业规划
- 黑马程序员——指针
- 黑马程序员——Java接口、类以及继承、实现
- 黑马程序员——分类与协议
- 黑马程序员——基础语法
- 黑马程序员——简单数据存储
- 黑马程序员——Java集合
- 程序员跳槽神级攻略
- 让程序员跳槽的非钱原因