黑马程序员——Java 集合(上)(第八篇)
来源:互联网 发布:微信外卖系统源码下载 编辑:程序博客网 时间:2024/06/06 01:40
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
(1)List与Set有什么区别?为什么
(2)HashSet与TreeSet有什么区别?它们之间是如何判断元素的唯一性
第一讲 集合框架
先看下面的图:
一、为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
二、数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象。
三、集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
Collection
|--List//元素是有序的,元素可以重复。因为该集合体系有索引。
|--Set//元素是无序的,元素不可以重复。
一、List
组成
List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
|--Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
二、List的特有方法
凡是可以操作角标的方法都是该体系特有的方法。
ArrayList al = newArrayList(); //添加元素 al.add("01"); al.add("02"); al.add("03"); al.add("04"); //获取个数,集合的长度 System.out.println(al.size()); //删除元素 al.remove("01"); //判断元素 System.out.println(al.contains("02")); ArrayList al2 = new ArrayList(); al2.add("01"); al2.add("02"); //取交集,al中存放的为交集 System.out.println(al.retainAll(al2)); System.out.println(al);
三、ListIterator
1、概述
ListIterator是List集合特有的迭代器,是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生ConcurrentModificationException异常。所以在迭代器时,只能用迭代器的方法操作元素。可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作。如果想要其他的操作,如添加、修改等,就需要使用其子接口:ListIterrator。该接口只能通过List集合的ListIterator方法获取。
2、ListIterator特有的方法
add(obj);//增加
set(obj);//修改为obj
hasPrevious();//判断前面有没有元素
previous();//取前一个元素
import java.util.LinkedList;import java.util.List;import java.util.ListIterator;public class TestListIterator{ public static void main(String args[]) { TestListIterator tliterator=new TestListIterator(); List<String> list=new LinkedList<String>(); tliterator.initial(list);//初始化这个链接表 ListIterator<String> li=list.listIterator();//将该链接表转化为ListIterator //下面的代码进行ListIterator对象li的各种功能检测 //顺序输出迭代器中的元素 while(li.hasNext()) {System.out.print(li.next().toString()+" ");} //验证add方法,给li添加两个元素 li.add("元素五"); li.add("元素六"); System.out.println();//产生换行操作 //通过使用ListIterator的特有方法hasPrevious与previous实现List的元素 //逆序输出 for(String str;li.hasPrevious();) {System.out.print(li.previous().toString()+" ");} System.out.println();//产生换行操作 //顺序输出li迭代器中现有的元素 while(li.hasNext()) {System.out.print(li.next().toString()+" ");} System.out.println();//产生换行操作 //通过使用ListIterator的set方法来改变li中的元素 for(String str;li.hasPrevious();) { str=li.previous().toString(); li.set(str.replaceAll("元素","元素编号")); } //顺序输出li迭代器中现有的元素 while(li.hasNext()) {System.out.print(li.next().toString()+" ");} } //初始化List方法 public void initial(List<String> list) { list.add("元素一"); list.add("元素二"); list.add("元素三"); list.add("元素四"); }}
四、枚举Enumeration
枚举:
就是Vector特有的取出方式。Vector有三种取出方式。
其实枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。
特有方法:
addElement(obj);//添加元素,相当于add(obj);
Enumerationelements();//Vector特有取出方式(枚举)
hasMoreElements();//相当于Iterator的hasNext()方法
nextElements();//相当于Iterator的next()方法
五、LinkedList
LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
LinkedList link= new LinkedList(); link.add("01"); link.add("02"); link.add("03"); //LinkedList的特有方法 link.addFirst("first");//在集合的开始添加元素 link.addLast("last");//在集合的结尾添加元素 System.out.println(link); link.getFirst();//得到集合的一个元素 link.getLast();//得到自己和的最后一个元素 link.removeFirst();//删除第一个元素,并得到 link.removeLast();//删除最后一个元素,并得到 //当集合中没有元素的时候,调用get和remove的方法会抛出异常 //使用pollFirst去替代remove,当没有元素的时候,返回null; //使用offerFirst()替换getFirst() link.clear(); System.out.println(link.pollFirst());//null
set 概述
在Collection中,除了List派系之外,还有一个Set派系,
List:元素是有序的(存入和取出的顺序一致),元素可以重复。因为该集合体系有索引。可以在指定位置对元素进行操作。凡是带角标的,底层的实现都是数组数据结构。
Set:元素是无序(存入和取出的顺序不一定一致)的,元素不可以重复。
查看Set接口的功能,才发现Set和Collection是一致的。(增删改查的功能)
在学习Set时候,最重要的是如何才能控制其中的元素唯一。
在Set接口下,有两个我们常用的类比较重要
HashSet:它的底层数据结构是哈希表(保证元素唯一性是判断元素的hashCode和equals方法。)
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
|--HashSet: 保证元素唯一性的原理:hashCode 与 equals
|--TreeSet: 保证元素唯一性的依据:compareTo
二、HasSet
HashSet:线程不安全,存取速度快。
HashSet hs = new HashSet(); hs.add("java01"); hs.add("java02"); hs.add("java03"); hs.add("java03");//返会false。表示为同一个元素 Iterator it = hs.iterator(); while(it.hasNext()) { System.out.println(it.next()); } //输出 java02 java03 java01定义一个Person类
class Person { private String name; private int age; public Person(String name,int age) { this.name = name; this.age = age; } @Override public String toString() { return this.name +"...."+this.age; } }并使用下边的例子实现
Person p = new Person("1",1); Person p2 = new Person("1",1); Person p1 = new Person("2",2); HashSet hs = new HashSet(); hs.add(p); hs.add(p1); hs.add(p2); Iterator it = hs.iterator(); while(it.hasNext()) { Person pp = (Person)it.next(); System.out.println(pp); } /输出: 1....1 1....1 2....2
说明相同的人被存入到HashSet中了,不满足HashSet所定义的那样了,必须处理自定义对象,使HashSet中不能存入相同的对象。(满足其原先定义的那样)
也就是必须让相同的对象其hash值相同。建立Person对象的hash值。
对象通过怎么判断相等(如Person中的age,name),就用这些值去生成hash值
对于底层数据结构是哈希表的数据结构的集合,如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals,如果元素的hashCode值相同,才会判断equals是否为true,如果元素的hashCode值不同,不会调用equals。所以不同的对象一般使其hashCode值不同,会更加的高效,不用去调用equels方法去判断是否相等。
三、TreeSet
1、特点
a、底层的数据结构为二叉树结构(红黑树结构)
b)可对Set集合中的元素进行排序,是因为:TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较,需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等)进行排序,并加入集合。
java中的很多类都具备比较性,其实就是实现了Comparable接口。
注意:排序时,当主要条件相同时,按次要条件排序。
class Student { private String name; public Student(String name, int age) { super(); this.name = name; this.age = age; } private int age; public String getName() { return name; } public int getAge() { return age; } public String toString() { return this.name+"...."+this.age; } } TreeSet ts = new TreeSet(); ts.add(new Student("01",10)); ts.add(new Student("02",13)); ts.add(new Student("03",11)); ts.add(new Student("04",22)); System.out.println(ts);
上面的列子报错了,原因是由于TreeSet要对放入其中的元素进行排序,但是按照什么顺序排,它并不知道,所以就报错了,也就是学生对象根本不具备比较性,所以要实现一个接口Comparable(也就是让存入的元素具备了比较性),此接口强行对实现它的每个类的对象进行整体排序,这种排序也称为类的自然排序。
元素实现Comparable接口,就是让元素具备了比较性。
public interface Comparable<T> { public int compareTo(T o); }强制让学生具备比较性。
class Student implements Comparable { public int compareTo(Object o) { Student s = (Student)o; return this.age - s.age; } }
c、保证数据的唯一性的依据:通过compareTo方法的返回值,是正整数、负整数或零,则两个对象较大、较小或相同。相等时则不会存入。
2、Tree排序的两种方式
1)第一种排序方式:自然排序
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也被称为元素的自然顺序,或者叫做默认顺序。
2)第二种方式:比较器
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
比较器构造方式:定义一个类,实现Comparator接口,覆盖compare方法。
当两种排序都存在时,以比较器为主。
第五讲 Map集合
该集合存储键值对。一对一对往里存,而且要保证键的唯一性(与Set集合保证元素唯一性一致)。一个映射不能包含重复的键。每个键最多只能映射到一个值。
Map集合中常见的三个子类对象
HashMap:底层是哈希表数据结构,线程不同步。允许使用null值和null键,效率高
HashTable:线程同步。不允许存入null值和null键,效率低
为了成功的在哈希表中存储和获取对象,用作键的对象必须实现hashCode方法和equals方法。
TreeMap:底层是二叉树数据结构,线程不同步,给键排序是它的主要特点。
其实Set底层就是使用了Map集合。
当Map仅存入一个键值的 时候,就是Set。
下边具体写一个例子来使用上述方法
import java.util.*; public class MapDemo { public static void main(String[] args) { Map<String,String> mp = new HashMap<String,String>(); System.out.println(mp.put("01","001")); System.out.println(mp.put("01","0001")); //在Map中存入一个键相同的值后,新的值会替换旧的值,这与set集合不同。 //旧的值通过put方法返回 mp.put("02", "002"); mp.put("03","003"); mp.put("04","004"); System.out.println(mp.containsKey("02")); System.out.println(mp.remove("01")); //当remove删除键在集合中不存在时候,返回null //当remove删除的键在集合中存在时,返回这个键所对应的值 System.out.println(mp); String s = mp.get("04"); //通过键去得到键所对应的值 System.out.println(s); mp.put(null,null); //HashMap中能存null键与null值 //获取map中所有的值 Collection<String> c = mp.values(); System.out.println(c); c.remove("002"); System.out.println(c); System.out.println(mp); } }
在Map中不能通过迭代器的方式去取出所有的元素,只用Collection体系下的集合才能使用Iterator去迭代取出。
有两种方式
keySet()
返回此映射中包含的键的 Set
视图。
将map中所有的键存入到Set集合中,由于Set具备迭代器,所以可以使用迭代方式取出所有的键,在根据get方法,获取每一个键对应的值。
例如
Map<String,String> mp = new HashMap<String,String>(); mp.put("02", "002"); mp.put("03","003"); mp.put("04","004"); Set<String> set = mp.keySet(); Iterator<String> it = set.iterator(); while(it.hasNext()) { String key = it.next(); System.out.println(key+"...."+mp.get(key)); }
entrySet()
返回此映射中包含的映射关系的 Set
视图。
Map<String,String> mp = new HashMap<String,String>(); mp.put("02", "002"); mp.put("03","003"); mp.put("04","004"); Set<Map.Entry<String,String>> set = mp.entrySet(); Iterator<Map.Entry<String,String>> it = set.iterator(); while(it.hasNext()) { Map.Entry<String,String> mpe = it.next(); System.out.println(mpe.getKey()+".."+mpe.getValue()); }
Map集合的取出原理,将Map集合转成Set集合,再通过迭代器取出。
在Map集合的子类中实现了Map.entry,对应集合的特定取出方式。跟迭代器原理一样。
上边的Map.entry类型其实就是关系类型。每一个键值对组成了一个关系。
- 黑马程序员——Java 集合(上)(第八篇)
- 黑马程序员——Java基础---集合类(上)
- 黑马程序员——Java基础---集合类(上)
- 黑马程序员——java基础---集合(上)
- 黑马程序员——Java之集合(上)
- 黑马程序员——集合(上)
- 黑马程序员——集合(上)
- 黑马程序员—集合(上)-Collection
- 黑马程序员 Java基础 ---> 集合(上)
- 黑马程序员《集合(上)》
- 黑马程序员-集合 (上)
- 黑马程序员——java基础--集合(篇一)
- 黑马程序员——java基础--集合(篇二)
- 黑马程序员Java笔记——集合篇(一)
- 黑马程序员Java笔记——集合篇(二)
- 黑马程序员——关于集合(上)
- 黑马程序员——JAVASE-集合(上)
- 黑马程序员——集合知识概括(上)
- IOS版本被拒的经历
- VS 2013使用SOUI时(vcpkgsrv.exe)进程导致物理内存升高解决的办法
- [Leetcode 232, Easy] Implement Queue using Stacks
- STL迭代器失效问题
- IE 不支持 jQuery的trim方法
- 黑马程序员——Java 集合(上)(第八篇)
- 杭电 hdu 1213 How Many Tables(经典并查集 基础题)
- maven下的pom.xml中定义的profile
- HDFS初识(TBC)
- POJ 1050:To the Max
- POJ 3253 Fence Repair(优先队列)
- PADS PCB 设置 MARK 点的方法
- Jmeter 通过读取文件参数化
- bzoj2850: 巧克力王国 kd-tree