我的java笔记(集合)
2012-08-21 23:32
316 查看
数据结构:按照某种方式组织数据的格式.
栈:先进后出.
队列:先进先出.
数组:存入和取出可以看成是无序的,但是如果顺序获取的话,它的存入和取出是一一对应的.
查询速度快,增删速度慢.
链表:链表数据结构是由一个个存储单元上非连续的节点组成.每个节点又由数据域和指针域组成.
查询速度慢,增删效率高.
一:
对象多了用集合存,数据多了用对象存.
集合是用于存储对象的一个工具,所以,也被称为容器.
数组和集合同是容器,不同点是:
1:数组是固定长度的,集合是可变长度的.
2:数组存储同一种类型,集合可以存储不同类型对象.
3:数组可以存储对象类型,也可以存储基本数据类型.
集合只能存储对象类型 .
相同点:都是容器,都可以存储多个数据.
数据结构:按照某种结构存储数据.
各种容器由于数据结构不同,所以,存储数据的方式不一样.
Collection:List-->ArrayList,LinkedList,Vector
Set--->HashSet,TreeSet
Collection:
1:存储数据:
boolean add(Object obj);增加一个元素.
boolean addAll(Collection c):增加一个集合的元素
2:删除数据:
void clear();删除集合中的所有元素.
boolean remove(Object o);移出单个元素.
boolean removeAll(Collection c);移出一个集合中和另一个集合相同的元素.
4:获取数据:
Iterator iterator();获取数据的迭代器
5:判断:
boolean contains(Object o):判断集合中是否包含某个元素.
contains底层是调用的equals方法.会自动调用.如果要按自己的需求判断,要覆写equals方法.
boolean containsAll(Collection c);判断集合是否包含某个小集合.
boolean isEmpty();判断集合是否为空.
6:长度:
int size();
7:交集:
boolean retainAll(Collection c):判断是否有交集,并把交集元素赋值给调用对象.
只要调用对象变化就返回true.A和B集合中的交集赋值给A,B不变.并且只要A集合中的元素有改变,那么,结果就是true,否则是false.
例如:如果A和B中没有相同的元素,那么会把空赋值给A集合,并返回true.
如果A和B中的元素相同,那么,A中的元素不变,返回值为false.
8:转换成数组:
Object[] toArray();集合转换成数组.
二:什么是迭代器?
其实迭代器是集合的取出元素的方式.
每一个容器的数据结构不同,所以取出元素的方式也不一样,这些取出方式被定义为内部类,但是他们都有
共性内容就是判断和取出,那么就可以将这些共性抽取.这些内部类都符合一个规则,该规则就是Iterator(内部类),
Iterator提供了一个对外方法:iterator();
迭代器返回的都是Object类型.
Iterator it=a1.iterator();其实返回的是接口的子类对象.
Iterator接口中的方法:
boolean hasNext():如果仍有元素可迭代则返回true;
Object next():获取元素.
例:
import java.util.ArrayList;
import java.util.Iterator;
public class Interator迭代器 {
public static void main(String args[]){
baseDemo();
}
public static void baseDemo(){
ArrayList a1=new ArrayList();
a1.add("java-1");
a1.add("java-2");
a1.add("java-3");
a1.add("java-4");
//此种方法在结束后迭代器不能及时回收
/*Iterator it=a1.iterator();//获取迭代器,用于取出集合中的元素.
while(it.hasNext()){ //判断集合中是否还有元素,如果有则返回true,
sop(it.next()); //it.next()方法是取出元素.
}*/
for(Iterator it=a1.iterator();it.hasNext();){ //工作中应该用这中,如果迭代器用完可以及时回收
String s=(String)it.next(); //需要强制类型转换,因为next()返回的是Object类型.
sop(s);
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
将自定义对象作为元素存到ArrayList集合中,并去除重复元素.
比如:存人对象,同姓名,同年龄,视为同一个人.为重复元素.
迭代器中返回的都是Object类型,需要强制类型转换.
例:String s=(String)it.next(); //需要强制类型转换,因为next()返回的是Object类型.
List 集合中判断元素是否相同用的是equals方法
remove和contains方法底层都是默认调用equals方法.
三:
List:元素是有序的(存入和取出顺序一样),元素可以重复.因为该集合体系有脚标索引
Set:元素无序,元素不可以重复.
LIst集合特有的方法:凡是可以操作角标的方法都是该体系特有的方法.
1:增加元素:add(element);向列表尾部添加指定的元素.
add(index,element);在指定位置插入指定元素.
addAll(index,Collection); 将Collection中的所有元素插入到列表中的指定位置.
2:删除元素:Object remove(index);移出指定位置的元素.
**3:改:set(index,element);把index位置上的元素用element替换
**4:获取元素:
get(int index); 返回指定位置上的元素
int indexof(Object obj);获取元素的位置
截取字符串:
List subList(begin,end);从List中取得一个小List.
大列表和子列表在内存中是有关联的:如果,你删除大列表中的某个元素,而这个元素
已经在子列表中获取过了,就会报ConcurrentModificationException异常.
在使用迭代器的时候最好不要在迭代器中删除元素,迭代器是根据集合来的,所以,你的修改回对集合产生影响.但是这样不好,最好在集合中操作.
** 5:listIterator():迭代元素
List集合特有的迭代器.ListIterator是Iterator的子接口.
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常(ConcurrentModificationException).
所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作.
如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator,该接口只能通过ListIterator集合的listIterator()方法获取.
boolean hasPrevious()如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。(从后往前判断)
E previous() 返回列表中的前一个元素(从后往前取)。
6:如何从List集合遍历元素?
(1):直接输出:System.out.println(list);
(2):迭代器Iterator it=list.iterator();
(3):for(int i=0;i<list.size(0;i++){
String s=(String)list.get(i);
System.out.println(s);
}
(4):ListIterator lit=list.listIterator();ListIterator是List特有的迭代器,提供了更多的方法操作.
四:
List下常见的三个子类对象:ArrayList,LinkedList,Vector
ArrayList:线程不是同步的,底层的数据结构使用的是数组结构.特点:查询速度很快,但是增删速度稍慢.
LinkedList:线程不同步,底层的数据结构是使用的链表数据结构.特点:查询速度慢,但增删速度快.
Vector:线程同步,底层是数组数据结构,功能和ArrayList相像,但是没有ArrayList效率高.被ArrayList替代了.
枚举是Vector特有的取出方式.
ArrayList是可变长度数组,初始容量为10,以50%增长.
Vector也是可变长度数组,初始容量也为10,以100%增长.
1:ArrayList没有特殊的方法,和父接口List中的方法一致,所以我们就直接使用.
2:Vector特有功能:
addElement(E) 增加元素
Object ElementAt(int index) 获取index处的元素
Enumeration elements():获取元素的枚举.
3:LinkedList的特有操作:
void addFirst(E e)将指定元素插入此列表的开头
void addLast(E e)将指定元素插入此列表的开头
getFirst()返回列表的第一个元素
getLast()返回列表的最后一个元素
获取元素,但是不删除元素,如果集合中没有元素,会出现NoSuchElementException异常
removeFirst()删除第一个元素
removeLast()删除最后一个元素.
获取元素,但是元素被删除,如果集合中没有元素,会出现NoSuchElementException异常
在JDK1.6出现了替代方法:
offerFirst(E e);
offerLast(E e);
在元素的开头或结尾插入指定的元素.
peekFirst();
peekLast();
获取开头或结尾元素,如果集合中没有元素,会返回null
pollFirst();
pollLast();
获取元素,但是元素被删除,如果集合中没有元素,会返回null
Set
五:Set集合和Collection的功能是一致的.没有新功能.
Set集合元素是无序(存入和取出的顺序不一定一致),元素不可以重复.
只能用迭代器取出元素,元素无序的是因为根据元素的哈希值来存放元素的.
Set最常用的子类是HashSet和TreeSet.
1:HashSet:底层数据结构是哈希表.存储的时候元素无序,但是集合本身内部
有一定规律的.存取速度快.
因为它是无序的所以不能依靠脚标获取元素.
一般使用HashSet的时候会重写hashCode方法和equals方法.
2:HashSet是如何保证元素的唯一性的呢?
由于HashSet地层数据结构是哈希表,它会根据哈希值进行存储.这个时候,我们如果要实现自己的需求,判断元素是否
唯一,就必须重写hashCode方法,并且重写equals方法.
如果元素的HashCode值相同,才会判断equals是否为true.
如果元素的HashCode值不同,就不调用equals.
这个结构叫做哈希表中的桶结构,当对象的哈希值相同的时候,它们是放在同一个地址处的,为了区分,它会自动根据equals进行判断.
所以在哈希值相同的情况下,我们只要重写equals犯法,判断各个对象的属性是否相同即可.
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法.
3:LinkedHashSet保证集合元素的有序唯一.
有序:读取和存储的顺序一致.
唯一:元素不能重复.
Linked用于保证元素的顺序有序.
Hash用于保证元素的唯一性.
六:TreeSet
1:HashSet:数据结构是哈希表,线程不同步.
保证元素唯一性的原理:判断元素的hashCode值是否相同.如果相同,还会继续判断元素的equals方法,是否为true.
TreeSet:底层数据结构是二叉树,不可以重复元素,线程是非同步的.默认顺序是根据自然(字典)排序的.
可以对Set集合中的元素进行排序.
存储字符串之所以能够保证排序,是因为字符串类实现了Comparable接口。
2:TreeSet如何保证元素的有序的呢?
(1):TreeSet元素需要实现Comparable接口中的compareTo方法,让元素自身具备比较性.这种方式也称为元素的自然排序,或者叫默认顺序.
(2):当元素自身不具备比较性时,或者具备的比较性不是所需要的.这时就需要让集合自身具备比较性,即在集合初始化时(构造函数),
实现Comparetor接口中的compare方法.(自定义比较器)
就有了比较方式.
例:
public class HashSetDemo_保证元素的唯一性 {
public static void main(String[] args) {
HashSet<Per> hs=new HashSet<Per>();
hs.add(new Per("lisi01",25));
hs.add(new Per("lisi02",21)); //
hs.add(new Per("lisi03",22)); //
hs.add(new Per("lisi01",25)); //
hs.add(new Per("lisi05",22));
hs.add(new Per("lisi02",21)); //
hs.add(new Per("lisi06",22));
hs.add(new Per("lisi03",20)); //
for(Iterator<Per> it=hs.iterator();it.hasNext();){
Per p=it.next();
System.out.println(p.getName()+"....."+p.getAge());
}
}
}
class Per{
private String name;
private int age;
public Per(){}
public Per(String name,int age){
this.name=name;
this.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;
}
public int hashCode(){ //覆写hashCode()方法.
return this.name.hashCode()+this.age*19; //this.age*19是为了防止意外出错:例如:hashCode=20,age=30;和hashCode=10,age=40;
}
public boolean equals(Object obj){ //覆写equals()方法.
if(this==obj){
return true;
}
if(!(obj instanceof Per)){
return false;
}
Per p=(Per)obj;
return this.getName().equals(p.getName())&&this.getAge()==p.getAge();
}
}
3:
TreeSet的第一种排序方式:让元素本身具备比较性,让Person类实现Comparable接口,覆写compareTo()方法.
Comparable接口:
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
此接口只有一个方法:
int compareTo(T t) 比较此对象与指定对象的顺序。
返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
记住:排序时,当主要条件相同时,一定要判断一下次要条件.
例:
public class TreeSet_保证集合元素有序的方法一 {
public static void main(String[] args) {
TreeSet<Stu> tr=new TreeSet<Stu>();
tr.add(new Stu("z三",23));
tr.add(new Stu("李四",20));
tr.add(new Stu("王五",28));
tr.add(new Stu("赵六",21));
tr.add(new Stu("qianqi",40));
tr.add(new Stu("李四",20));
tr.add(new Stu("w五",23));
for(Iterator<Stu> it=tr.iterator();it.hasNext();){
Stu s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}
}
class Stu implements Comparable<Stu>{
private String name;
private int age;
public Stu(){}
public Stu(String name,int age){
this.name=name;
this.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;
}
public int compareTo(Stu s) { //重写compareTo方法;
//判断主要条件
int num=this.age-s.age; //按年龄大小排序
//判断次要条件
return num==0?this.name.compareTo(s.name):num; //如果主要条件相同,则判比较次要条件.
}
}
4:
TreeSet的第二种排序方式:使用TreeSet带比较器的构造.
当元素自身不具备比较性时,或具备的比较性不是所需要的,
这时就需要集合自身具备比较性.这时就要集合初始化时就具备比较性.
定义比较器,将比较器对象作为参数传递给TreeSet集合
如果两种排序都存在时,以比较器为主.
定义一个类实现Comparator接口,并覆写compare方法.如果return 0 则表示两个对象为同一对象.
int compare(T o1, T o2)
比较用来排序的两个参数。
boolean equals(Object obj)
指示某个其他对象是否“等于”此 Comparator。
例:
public class TreeSet_保证集合元素有序的方法二 {
public static void main(String[] args) {
//使用TreeSet的带比较器的构造
TreeSet<People> tr = new TreeSet<People>(new ComparatorImp()); //将比较器作为参数传递到TreeSet中
/*//使用匿名内部类
TreeSet<People> tr=new TreeSet<People>(new Comparator<People>(){
public int compare(People o1,People o2){
int num1=o1.getName().length()-o2.getName().length();
int num2=o1.getAge()-o2.getAge();
int compareTo(String anotherString) 按字典顺序比较两个字符串。
int num3=o1.getName().compareTo(o2.getName());
return num1==0?(num2==0?num3:num2):num1;
//如果名字的长度相同就按年龄排序,如果年龄相同就按名字的自然顺序排序.
}
});*/
tr.add(new People("z三",23));
tr.add(new People("李四",20));
tr.add(new People("王五而热热",28));
tr.add(new People("赵六而",21));
tr.add(new People("qianqi",40));
tr.add(new People("李四",20));
tr.add(new People("w五",23));
for(Iterator<People> it=tr.iterator();it.hasNext();){
People s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}
}
class People{
private String name;
private int age;
public People(){}
public People(String name,int age){
this.name=name;
this.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;
}
}
class ComparatorImp implements Comparator<People>{ //定义一个比较器
@Override
public int compare(People o1, People o2) {
int num1=o1.getName().length()-o2.getName().length();
int num2=o1.getAge()-o2.getAge();
/*
int compareTo(String anotherString) 按字典顺序比较两个字符串。
*/
int num3=o1.getName().compareTo(o2.getName());
return num1==0?(num2==0?num3:num2):num1;
//如果名字的长度相同就按年龄排序,如果年龄相同就按名字的自然顺序排序.
}
}
//当添加第二个元素时,TreeSet集合会自动去调用比较器中的compare方法.
七:以后到底用哪个集合呢?
1:如果元素唯一,就用Set.否则用List.
2:如果元素唯一并且要排序用TreeSet,否则用HashSet.
3:如果元素可重复,且考虑线程安全,用Vector.否则,用ArrayList或者LinkedList.
如果要求,增删快,那么,考虑LinkedList.
如果要求,查询快,那么,考虑ArrayList.
4:当你什么都不清楚的时候,就使用ArrayList.
Array:想到数组,就应该想到数据的索引.
Link:想到链表,就应该想到增删快. 最好能想到addFrist.
Hash:想到哈希表,就应该想到元素的hashCode和equals方法.
Tree:想到二叉树
八:泛型
1:泛型:JDK1.5版本以后出现新特性,用于解决安全问题,是一个安全机制.
好处:
(1)将运行时期出现的问题ClassCastException,转移到了编译时期,
方便于程序员解决问题,让运行事情问题减少,增加安全性.
(2)避免了使用数据的时候强制转换的麻烦.
2:泛型格式:通过<>来定义要操作的"引用数据类型".<>是用来接收类型
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可.
3:什么时候使用泛型?:一般用于集合类中
通常在集合框架中很常见,只要见到<>就要定义泛型
当类中要操作的引用数据类型不确定的时候,定义泛型阿里完成扩展.
早期没有泛型之前定义Object来完成扩展.
4:?通配符,也可以理解为占位符.
? extends E:可以接收E类型或者E的子类型.上限.
? super E:可以接收E类型或者E的父类型.下限.
5:泛型在类中的使用:
class Demo<T>{
public void show(T t){}
}
6:泛型定义在方法中:
class Demo{
public<T> void show(T t){
System.out.println(bm);
}
}
7:泛型定义在接口中
interface Inter<QQ>{
public sbstract void show(QQ qq);
}
class InterImpl<QQ> implements Inter<QQ> {
public void show(QQ qq) {
System.out.println("show:" + qq);
}
}
6:自定义泛型类:防止多态存在安全隐患.
例1:
import java.util.*;
public class Fanxing {
public static void main(String[] args) {
TreeSet<String> ts=new TreeSet<String>(new MyComparator());
ts.add("dfa");
ts.add("fwoijf");
ts.add("dsswo");
ts.add("fdjow");
ts.add("fwef");
for(Iterator<String> it=ts.iterator();it.hasNext();){
String s=it.next();
System.out.println(s);
}
}
}
class MyComparator implements Comparator<String> //默认的是Object类型
{
public int compare(String o1,String o2){
int num = new Integer(o1.length()).compareTo(new Integer(o2.length())); //把o1和o2调换则会反向输出.
if(num==0){
return o1.compareTo(o2) ;
}
return num;
}
}
例2:将泛型定义在类,和方法上
class Demo<QQ>
{
public void show(QQ ss){
System.out.println("show:"+ss);
}
//泛型加在方法上
public <BM> void method(BM bm){
System.out.println("method:"+bm);
}
}
public class GenericDemo4 {
public static void main(String[] args) {
Demo<String> d = new Demo<String>();
d.show("aa");
Demo<Integer> d2 = new Demo<Integer>();
d2.show(20);
Demo<Float> d3 = new Demo<Float>();
d3.show(20.5f);
d3.method("aa");
d3.method(20);
d3.method(20.5f);
}
}
九:Map接口:
Map的体系结构:
|--Hashtable
底层是哈希表结构
线程安全的,并且键和值不能为null。
|--HashMap
底层是哈希表结构
线程不安全的,键和值可以为null。
|--LinkedHashMap
底层是链表和哈希表
线程不安全
|--TreeMap
底层是二叉树
线程不安全的
1:Map接口和Collection接口的区别:
Map是键值对的方式,是双列的方式
Collection是单列的方式.
(1): Map中一次存储是键值对。
Collection中一次存储是单个元素。
(2): Map的存储使用的put方法。
Collection存储使用的是add方法。
(3): Map的取出,是将Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
(4): 如果对象很多,必须使用容器存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。
2:
Map<K,V>:K是存储的键,V是键对应的值.
键是唯一的.
3:Map的功能:
(1):获取数据:
Set<Map.Entry<K,V>> entrySet():返回键值对的Set视图.
Object get(Object key):根据键得到值
Set<K> keySet():返回键的Set集合.
得到所有的键.
Collection<V> values(); 返回的就是值的Collection集合.
得到所有的值.
(2):存储数据:
Object put(K key,V value):存储元素
(3):删除数据:
clear():移出所有元素.
Object remove(Object key):根据指定的键删除元素.
(4):判断:
boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回true.
boolean containsValue(Object value)如果此映射将一个或多个键映射到指定值,则返回true.
boolean isEmpty():判断是否为空.
(5):int size():获取Map的键值对的个数.
4:如何遍历Map:
单独使用Map的键或值的集合的时候,可以分别使用:keySet和value方法
真正意义上的遍历,有两种方式:
第一种:
思路:
先获取键的集合.Set<K> keySet():返回键的Set集合.得到所有的键.
遍历键的集合,获取到每一个键值.Collection<V> values(); 返回的就是值的Collection集合.
根据每一个键值,调用Map的get方法,获取每一个键值对应的值
第二种:
Set<Map.Entry<K,V>> entrySet()
思路:先获取键值对对象的集合.
遍历这个对象的集合.
根据遍历的每一个对象,获取键和值.
举例: 先获取夫妻的结婚证的集合.
遍历这个集合,获取到每一张结婚证.
按照结婚证上的名字获取每一个丈夫和妻子.
例:
public class MapDemo {
public static void main(String[] args) {
HashMap<String,Student> hmp=new HashMap<String,Student>();
hmp.put("001", new Student("张三",29));
hmp.put("004", new Student("赵六",23));
hmp.put("003", new Student("网速",12));
hmp.put("002", new Student("李四",30));
hmp.put("005", new Student("钱起",56));
//第一种方法:
/*Set<String> keySets = hmp.keySet();
Iterator<String> it3 = keySets.iterator();
while(it3.hasNext()){
String key = it3.next();
Student value = hmp.get(key);
System.out.println(key+"***"+value);
}
System.out.println("*************************");
*/
//第二种方法:
Set<Map.Entry<String,Student>> setmp=hmp.entrySet();
for(Iterator<Map.Entry<String,Student>> it=setmp.iterator();it.hasNext();){
Map.Entry<String,Student> mape=it.next();
String s=mape.getKey();
Student stu=mape.getValue();
System.out.println(s+"..."+stu.getName()+"....."+stu.getAge());
}
}
}
class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age){
this.name=name;
this.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;
}
}
5:HashMap
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键
此实现不是同步的
例:保证元素的唯一性:
public class HashMap_保证元素的唯一性 {
public static void main(String[] args) {
HashMap<String,Integer> hm=new HashMap<String,Integer>();
hm.put("张三", 23);
hm.put("李四", 24);
hm.put("王五", 39);
hm.put("朱丽叶", 19);
hm.put("梁山泊", 23);
hm.put("王五", 39);
Set<String> set=hm.keySet();
for(Iterator<String> it=set.iterator();it.hasNext();){
String key=it.next(); //获取键
Integer value=hm.get(key); //获取值
System.out.println(key+"....."+value);
}
}
}
class Stu {
private String name;
private int age;
public Stu(){}
public Stu(String name,int age){
this.name=name;
this.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;
}
public boolean equals(Object obj){ //覆写equals方法
if(this==obj){
return true;
}
if(!(obj instanceof Stu)){
return false;
}
Stu s=(Stu)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
public int hashCode(){ //覆写hashCode方法
return this.name.hashCode()+this.age*17;
}
}
例2:HashMap的嵌套:
/*
传智播客:
jc|基础班
001 张三
002 李四
jy|就业班
001 王五
002 赵六
分析:
1:在大集合中嵌套小集合
3:传智播客是一个大集合
4:基础班和就业班又是一个集合.
5:在小集合中学号为键,Student对象为值.
*/
public class HashMap_集合嵌套 {
public static void main(String[] args) {
HashMap<String,HashMap<String,String>> hm=new HashMap<String,HashMap<String,String>>(); //大集合
HashMap<String,String> hm1=new HashMap<String,String>(); //小集合基础班
hm1.put("001", "张三");
hm1.put("002", "李四");
HashMap<String,String> hm2=new HashMap<String,String>(); //小集合就业班
hm2.put("001", "王五");
hm2.put("002", "赵六");
hm.put("基础班",hm1);
hm.put("就业班",hm2);
Set<String> set=hm.keySet();
for(Iterator<String> it=set.iterator();it.hasNext();){
String str1=it.next(); //取得大集合的键
HashMap<String,String> hp=hm.get(str1); //取得大集合的值
System.out.println(str1);
Set<String> ss=hp.keySet(); //得到小集合的所有键
for(Iterator<String> itt=ss.iterator();itt.hasNext();){
String str2=itt.next(); //取得小集合的键
String str3=hp.get(str2); //取得小集合的值
System.out.println("\t"+str2+"....."+str3);
}
}
}
}
6:TreeMap:
基于二叉树实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,
具体取决于使用的构造方法。
例:
1:按照年龄排序,如果年龄相同按姓名排,让元素本身具有比较性实现Comparable接口
2:根据名字的长度排序,并且让集合本身具有比较性.
*/
public class TreeMap_保证元素的有序性 {
public static void main(String[] args) {
//内部类方式
/* TreeMap<Person,String> tmp=new TreeMap<Person,String>(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int num=p1.getAge()-p2.getAge();
int num1=p1.getName().compareTo(p2.getName());
return num==0?num1:num;
}
});*/
//使用比较器,让集合具备比较性
TreeMap<Person,String> tmp=new TreeMap<Person,String>(new ComImp());
//让元素自身具有比较性
//TreeMap<Person,String> tmp=new TreeMap<Person,String>();
tmp.put(new Person("ly刘亦菲",22),"001");
tmp.put(new Person("ls刘诗诗", 2),"002");
tmp.put(new Person("杨幂",30),"003");
tmp.put(new Person("李冰冰",25),"004");
Set<Person> set=tmp.keySet();
for(Iterator<Person> it=set.iterator();it.hasNext();){
Person key=it.next();
String value=tmp.get(key);
System.out.println(key.getName()+"....."+key.getAge()+"..."+value);
}
}
}
class Person implements Comparable<Person> { //让元素自身具有比较性
private String name;
private int age;
public Person(){}
public Person(String name,int age){
this.name=name;
this.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;
}
@Override
public int compareTo(Person p) {
int num=this.age-p.age;
int num1=this.name.compareTo(p.name);
return num==0?num1:num;
}
}
class ComImp implements Comparator<Person>{
@Override
public int compare(Person p1, Person p2) {
int num=p1.getAge()-p2.getAge();
int num1=p1.getName().compareTo(p2.getName());
return num==0?num1:num;
}
}
7:Collections: Collection的工具类.
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
排序: sort();
二分查找: binarySearch();
反转: reverse();
8:Arrays: 数组操作的工具类.
toString(基本数据类型[])把数组用字符串输出.
sort();排序
binarySearch();二分查找.
9:增强for循环:
格式:
for(元素的数据类型 变量名:数组或Collection集合)
{
执行语句;
}
好处:
简化了对数组,集合的遍历.
例:for(int x:arr){
System.out.println(x);//自动从数组arr中的0索引出开始,获取每一个值赋给x.
}
10:方法的另一种形式:可变参数方法
返回值类型 函数名(数据类型... 数组名){}
注意:假如有多个参数的时候,而且你的参数有可变参数,这个时候,可变参数必须置于方法参数的最后边.
例: int run(int b,int...a){}
11:静态导入:
import默认导入是导入到类级别.
而静态导入是导入到方法的级别.
格式:
import static 类名.方法;
栈:先进后出.
队列:先进先出.
数组:存入和取出可以看成是无序的,但是如果顺序获取的话,它的存入和取出是一一对应的.
查询速度快,增删速度慢.
链表:链表数据结构是由一个个存储单元上非连续的节点组成.每个节点又由数据域和指针域组成.
查询速度慢,增删效率高.
一:
对象多了用集合存,数据多了用对象存.
集合是用于存储对象的一个工具,所以,也被称为容器.
数组和集合同是容器,不同点是:
1:数组是固定长度的,集合是可变长度的.
2:数组存储同一种类型,集合可以存储不同类型对象.
3:数组可以存储对象类型,也可以存储基本数据类型.
集合只能存储对象类型 .
相同点:都是容器,都可以存储多个数据.
数据结构:按照某种结构存储数据.
各种容器由于数据结构不同,所以,存储数据的方式不一样.
Collection:List-->ArrayList,LinkedList,Vector
Set--->HashSet,TreeSet
Collection:
1:存储数据:
boolean add(Object obj);增加一个元素.
boolean addAll(Collection c):增加一个集合的元素
2:删除数据:
void clear();删除集合中的所有元素.
boolean remove(Object o);移出单个元素.
boolean removeAll(Collection c);移出一个集合中和另一个集合相同的元素.
4:获取数据:
Iterator iterator();获取数据的迭代器
5:判断:
boolean contains(Object o):判断集合中是否包含某个元素.
contains底层是调用的equals方法.会自动调用.如果要按自己的需求判断,要覆写equals方法.
boolean containsAll(Collection c);判断集合是否包含某个小集合.
boolean isEmpty();判断集合是否为空.
6:长度:
int size();
7:交集:
boolean retainAll(Collection c):判断是否有交集,并把交集元素赋值给调用对象.
只要调用对象变化就返回true.A和B集合中的交集赋值给A,B不变.并且只要A集合中的元素有改变,那么,结果就是true,否则是false.
例如:如果A和B中没有相同的元素,那么会把空赋值给A集合,并返回true.
如果A和B中的元素相同,那么,A中的元素不变,返回值为false.
8:转换成数组:
Object[] toArray();集合转换成数组.
二:什么是迭代器?
其实迭代器是集合的取出元素的方式.
每一个容器的数据结构不同,所以取出元素的方式也不一样,这些取出方式被定义为内部类,但是他们都有
共性内容就是判断和取出,那么就可以将这些共性抽取.这些内部类都符合一个规则,该规则就是Iterator(内部类),
Iterator提供了一个对外方法:iterator();
迭代器返回的都是Object类型.
Iterator it=a1.iterator();其实返回的是接口的子类对象.
Iterator接口中的方法:
boolean hasNext():如果仍有元素可迭代则返回true;
Object next():获取元素.
例:
import java.util.ArrayList;
import java.util.Iterator;
public class Interator迭代器 {
public static void main(String args[]){
baseDemo();
}
public static void baseDemo(){
ArrayList a1=new ArrayList();
a1.add("java-1");
a1.add("java-2");
a1.add("java-3");
a1.add("java-4");
//此种方法在结束后迭代器不能及时回收
/*Iterator it=a1.iterator();//获取迭代器,用于取出集合中的元素.
while(it.hasNext()){ //判断集合中是否还有元素,如果有则返回true,
sop(it.next()); //it.next()方法是取出元素.
}*/
for(Iterator it=a1.iterator();it.hasNext();){ //工作中应该用这中,如果迭代器用完可以及时回收
String s=(String)it.next(); //需要强制类型转换,因为next()返回的是Object类型.
sop(s);
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
将自定义对象作为元素存到ArrayList集合中,并去除重复元素.
比如:存人对象,同姓名,同年龄,视为同一个人.为重复元素.
迭代器中返回的都是Object类型,需要强制类型转换.
例:String s=(String)it.next(); //需要强制类型转换,因为next()返回的是Object类型.
List 集合中判断元素是否相同用的是equals方法
remove和contains方法底层都是默认调用equals方法.
三:
List:元素是有序的(存入和取出顺序一样),元素可以重复.因为该集合体系有脚标索引
Set:元素无序,元素不可以重复.
LIst集合特有的方法:凡是可以操作角标的方法都是该体系特有的方法.
1:增加元素:add(element);向列表尾部添加指定的元素.
add(index,element);在指定位置插入指定元素.
addAll(index,Collection); 将Collection中的所有元素插入到列表中的指定位置.
2:删除元素:Object remove(index);移出指定位置的元素.
**3:改:set(index,element);把index位置上的元素用element替换
**4:获取元素:
get(int index); 返回指定位置上的元素
int indexof(Object obj);获取元素的位置
截取字符串:
List subList(begin,end);从List中取得一个小List.
大列表和子列表在内存中是有关联的:如果,你删除大列表中的某个元素,而这个元素
已经在子列表中获取过了,就会报ConcurrentModificationException异常.
在使用迭代器的时候最好不要在迭代器中删除元素,迭代器是根据集合来的,所以,你的修改回对集合产生影响.但是这样不好,最好在集合中操作.
** 5:listIterator():迭代元素
List集合特有的迭代器.ListIterator是Iterator的子接口.
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常(ConcurrentModificationException).
所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作.
如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator,该接口只能通过ListIterator集合的listIterator()方法获取.
boolean hasPrevious()如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。(从后往前判断)
E previous() 返回列表中的前一个元素(从后往前取)。
6:如何从List集合遍历元素?
(1):直接输出:System.out.println(list);
(2):迭代器Iterator it=list.iterator();
(3):for(int i=0;i<list.size(0;i++){
String s=(String)list.get(i);
System.out.println(s);
}
(4):ListIterator lit=list.listIterator();ListIterator是List特有的迭代器,提供了更多的方法操作.
四:
List下常见的三个子类对象:ArrayList,LinkedList,Vector
ArrayList:线程不是同步的,底层的数据结构使用的是数组结构.特点:查询速度很快,但是增删速度稍慢.
LinkedList:线程不同步,底层的数据结构是使用的链表数据结构.特点:查询速度慢,但增删速度快.
Vector:线程同步,底层是数组数据结构,功能和ArrayList相像,但是没有ArrayList效率高.被ArrayList替代了.
枚举是Vector特有的取出方式.
ArrayList是可变长度数组,初始容量为10,以50%增长.
Vector也是可变长度数组,初始容量也为10,以100%增长.
1:ArrayList没有特殊的方法,和父接口List中的方法一致,所以我们就直接使用.
2:Vector特有功能:
addElement(E) 增加元素
Object ElementAt(int index) 获取index处的元素
Enumeration elements():获取元素的枚举.
3:LinkedList的特有操作:
void addFirst(E e)将指定元素插入此列表的开头
void addLast(E e)将指定元素插入此列表的开头
getFirst()返回列表的第一个元素
getLast()返回列表的最后一个元素
获取元素,但是不删除元素,如果集合中没有元素,会出现NoSuchElementException异常
removeFirst()删除第一个元素
removeLast()删除最后一个元素.
获取元素,但是元素被删除,如果集合中没有元素,会出现NoSuchElementException异常
在JDK1.6出现了替代方法:
offerFirst(E e);
offerLast(E e);
在元素的开头或结尾插入指定的元素.
peekFirst();
peekLast();
获取开头或结尾元素,如果集合中没有元素,会返回null
pollFirst();
pollLast();
获取元素,但是元素被删除,如果集合中没有元素,会返回null
Set
五:Set集合和Collection的功能是一致的.没有新功能.
Set集合元素是无序(存入和取出的顺序不一定一致),元素不可以重复.
只能用迭代器取出元素,元素无序的是因为根据元素的哈希值来存放元素的.
Set最常用的子类是HashSet和TreeSet.
1:HashSet:底层数据结构是哈希表.存储的时候元素无序,但是集合本身内部
有一定规律的.存取速度快.
因为它是无序的所以不能依靠脚标获取元素.
一般使用HashSet的时候会重写hashCode方法和equals方法.
2:HashSet是如何保证元素的唯一性的呢?
由于HashSet地层数据结构是哈希表,它会根据哈希值进行存储.这个时候,我们如果要实现自己的需求,判断元素是否
唯一,就必须重写hashCode方法,并且重写equals方法.
如果元素的HashCode值相同,才会判断equals是否为true.
如果元素的HashCode值不同,就不调用equals.
这个结构叫做哈希表中的桶结构,当对象的哈希值相同的时候,它们是放在同一个地址处的,为了区分,它会自动根据equals进行判断.
所以在哈希值相同的情况下,我们只要重写equals犯法,判断各个对象的属性是否相同即可.
注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法.
3:LinkedHashSet保证集合元素的有序唯一.
有序:读取和存储的顺序一致.
唯一:元素不能重复.
Linked用于保证元素的顺序有序.
Hash用于保证元素的唯一性.
六:TreeSet
1:HashSet:数据结构是哈希表,线程不同步.
保证元素唯一性的原理:判断元素的hashCode值是否相同.如果相同,还会继续判断元素的equals方法,是否为true.
TreeSet:底层数据结构是二叉树,不可以重复元素,线程是非同步的.默认顺序是根据自然(字典)排序的.
可以对Set集合中的元素进行排序.
存储字符串之所以能够保证排序,是因为字符串类实现了Comparable接口。
2:TreeSet如何保证元素的有序的呢?
(1):TreeSet元素需要实现Comparable接口中的compareTo方法,让元素自身具备比较性.这种方式也称为元素的自然排序,或者叫默认顺序.
(2):当元素自身不具备比较性时,或者具备的比较性不是所需要的.这时就需要让集合自身具备比较性,即在集合初始化时(构造函数),
实现Comparetor接口中的compare方法.(自定义比较器)
就有了比较方式.
例:
public class HashSetDemo_保证元素的唯一性 {
public static void main(String[] args) {
HashSet<Per> hs=new HashSet<Per>();
hs.add(new Per("lisi01",25));
hs.add(new Per("lisi02",21)); //
hs.add(new Per("lisi03",22)); //
hs.add(new Per("lisi01",25)); //
hs.add(new Per("lisi05",22));
hs.add(new Per("lisi02",21)); //
hs.add(new Per("lisi06",22));
hs.add(new Per("lisi03",20)); //
for(Iterator<Per> it=hs.iterator();it.hasNext();){
Per p=it.next();
System.out.println(p.getName()+"....."+p.getAge());
}
}
}
class Per{
private String name;
private int age;
public Per(){}
public Per(String name,int age){
this.name=name;
this.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;
}
public int hashCode(){ //覆写hashCode()方法.
return this.name.hashCode()+this.age*19; //this.age*19是为了防止意外出错:例如:hashCode=20,age=30;和hashCode=10,age=40;
}
public boolean equals(Object obj){ //覆写equals()方法.
if(this==obj){
return true;
}
if(!(obj instanceof Per)){
return false;
}
Per p=(Per)obj;
return this.getName().equals(p.getName())&&this.getAge()==p.getAge();
}
}
3:
TreeSet的第一种排序方式:让元素本身具备比较性,让Person类实现Comparable接口,覆写compareTo()方法.
Comparable接口:
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
此接口只有一个方法:
int compareTo(T t) 比较此对象与指定对象的顺序。
返回:负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
记住:排序时,当主要条件相同时,一定要判断一下次要条件.
例:
public class TreeSet_保证集合元素有序的方法一 {
public static void main(String[] args) {
TreeSet<Stu> tr=new TreeSet<Stu>();
tr.add(new Stu("z三",23));
tr.add(new Stu("李四",20));
tr.add(new Stu("王五",28));
tr.add(new Stu("赵六",21));
tr.add(new Stu("qianqi",40));
tr.add(new Stu("李四",20));
tr.add(new Stu("w五",23));
for(Iterator<Stu> it=tr.iterator();it.hasNext();){
Stu s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}
}
class Stu implements Comparable<Stu>{
private String name;
private int age;
public Stu(){}
public Stu(String name,int age){
this.name=name;
this.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;
}
public int compareTo(Stu s) { //重写compareTo方法;
//判断主要条件
int num=this.age-s.age; //按年龄大小排序
//判断次要条件
return num==0?this.name.compareTo(s.name):num; //如果主要条件相同,则判比较次要条件.
}
}
4:
TreeSet的第二种排序方式:使用TreeSet带比较器的构造.
当元素自身不具备比较性时,或具备的比较性不是所需要的,
这时就需要集合自身具备比较性.这时就要集合初始化时就具备比较性.
定义比较器,将比较器对象作为参数传递给TreeSet集合
如果两种排序都存在时,以比较器为主.
定义一个类实现Comparator接口,并覆写compare方法.如果return 0 则表示两个对象为同一对象.
int compare(T o1, T o2)
比较用来排序的两个参数。
boolean equals(Object obj)
指示某个其他对象是否“等于”此 Comparator。
例:
public class TreeSet_保证集合元素有序的方法二 {
public static void main(String[] args) {
//使用TreeSet的带比较器的构造
TreeSet<People> tr = new TreeSet<People>(new ComparatorImp()); //将比较器作为参数传递到TreeSet中
/*//使用匿名内部类
TreeSet<People> tr=new TreeSet<People>(new Comparator<People>(){
public int compare(People o1,People o2){
int num1=o1.getName().length()-o2.getName().length();
int num2=o1.getAge()-o2.getAge();
int compareTo(String anotherString) 按字典顺序比较两个字符串。
int num3=o1.getName().compareTo(o2.getName());
return num1==0?(num2==0?num3:num2):num1;
//如果名字的长度相同就按年龄排序,如果年龄相同就按名字的自然顺序排序.
}
});*/
tr.add(new People("z三",23));
tr.add(new People("李四",20));
tr.add(new People("王五而热热",28));
tr.add(new People("赵六而",21));
tr.add(new People("qianqi",40));
tr.add(new People("李四",20));
tr.add(new People("w五",23));
for(Iterator<People> it=tr.iterator();it.hasNext();){
People s=it.next();
System.out.println(s.getName()+"....."+s.getAge());
}
}
}
class People{
private String name;
private int age;
public People(){}
public People(String name,int age){
this.name=name;
this.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;
}
}
class ComparatorImp implements Comparator<People>{ //定义一个比较器
@Override
public int compare(People o1, People o2) {
int num1=o1.getName().length()-o2.getName().length();
int num2=o1.getAge()-o2.getAge();
/*
int compareTo(String anotherString) 按字典顺序比较两个字符串。
*/
int num3=o1.getName().compareTo(o2.getName());
return num1==0?(num2==0?num3:num2):num1;
//如果名字的长度相同就按年龄排序,如果年龄相同就按名字的自然顺序排序.
}
}
//当添加第二个元素时,TreeSet集合会自动去调用比较器中的compare方法.
七:以后到底用哪个集合呢?
1:如果元素唯一,就用Set.否则用List.
2:如果元素唯一并且要排序用TreeSet,否则用HashSet.
3:如果元素可重复,且考虑线程安全,用Vector.否则,用ArrayList或者LinkedList.
如果要求,增删快,那么,考虑LinkedList.
如果要求,查询快,那么,考虑ArrayList.
4:当你什么都不清楚的时候,就使用ArrayList.
Array:想到数组,就应该想到数据的索引.
Link:想到链表,就应该想到增删快. 最好能想到addFrist.
Hash:想到哈希表,就应该想到元素的hashCode和equals方法.
Tree:想到二叉树
八:泛型
1:泛型:JDK1.5版本以后出现新特性,用于解决安全问题,是一个安全机制.
好处:
(1)将运行时期出现的问题ClassCastException,转移到了编译时期,
方便于程序员解决问题,让运行事情问题减少,增加安全性.
(2)避免了使用数据的时候强制转换的麻烦.
2:泛型格式:通过<>来定义要操作的"引用数据类型".<>是用来接收类型
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可.
3:什么时候使用泛型?:一般用于集合类中
通常在集合框架中很常见,只要见到<>就要定义泛型
当类中要操作的引用数据类型不确定的时候,定义泛型阿里完成扩展.
早期没有泛型之前定义Object来完成扩展.
4:?通配符,也可以理解为占位符.
? extends E:可以接收E类型或者E的子类型.上限.
? super E:可以接收E类型或者E的父类型.下限.
5:泛型在类中的使用:
class Demo<T>{
public void show(T t){}
}
6:泛型定义在方法中:
class Demo{
public<T> void show(T t){
System.out.println(bm);
}
}
7:泛型定义在接口中
interface Inter<QQ>{
public sbstract void show(QQ qq);
}
class InterImpl<QQ> implements Inter<QQ> {
public void show(QQ qq) {
System.out.println("show:" + qq);
}
}
6:自定义泛型类:防止多态存在安全隐患.
例1:
import java.util.*;
public class Fanxing {
public static void main(String[] args) {
TreeSet<String> ts=new TreeSet<String>(new MyComparator());
ts.add("dfa");
ts.add("fwoijf");
ts.add("dsswo");
ts.add("fdjow");
ts.add("fwef");
for(Iterator<String> it=ts.iterator();it.hasNext();){
String s=it.next();
System.out.println(s);
}
}
}
class MyComparator implements Comparator<String> //默认的是Object类型
{
public int compare(String o1,String o2){
int num = new Integer(o1.length()).compareTo(new Integer(o2.length())); //把o1和o2调换则会反向输出.
if(num==0){
return o1.compareTo(o2) ;
}
return num;
}
}
例2:将泛型定义在类,和方法上
class Demo<QQ>
{
public void show(QQ ss){
System.out.println("show:"+ss);
}
//泛型加在方法上
public <BM> void method(BM bm){
System.out.println("method:"+bm);
}
}
public class GenericDemo4 {
public static void main(String[] args) {
Demo<String> d = new Demo<String>();
d.show("aa");
Demo<Integer> d2 = new Demo<Integer>();
d2.show(20);
Demo<Float> d3 = new Demo<Float>();
d3.show(20.5f);
d3.method("aa");
d3.method(20);
d3.method(20.5f);
}
}
九:Map接口:
Map的体系结构:
|--Hashtable
底层是哈希表结构
线程安全的,并且键和值不能为null。
|--HashMap
底层是哈希表结构
线程不安全的,键和值可以为null。
|--LinkedHashMap
底层是链表和哈希表
线程不安全
|--TreeMap
底层是二叉树
线程不安全的
1:Map接口和Collection接口的区别:
Map是键值对的方式,是双列的方式
Collection是单列的方式.
(1): Map中一次存储是键值对。
Collection中一次存储是单个元素。
(2): Map的存储使用的put方法。
Collection存储使用的是add方法。
(3): Map的取出,是将Map转成Set,在使用迭代器取出。
Collection取出,使用就是迭代器。
(4): 如果对象很多,必须使用容器存储。
如果元素存在着映射关系,可以优先考虑使用Map存储或者用数组,
如果没有映射关系,可以使用Collection存储。
2:
Map<K,V>:K是存储的键,V是键对应的值.
键是唯一的.
3:Map的功能:
(1):获取数据:
Set<Map.Entry<K,V>> entrySet():返回键值对的Set视图.
Object get(Object key):根据键得到值
Set<K> keySet():返回键的Set集合.
得到所有的键.
Collection<V> values(); 返回的就是值的Collection集合.
得到所有的值.
(2):存储数据:
Object put(K key,V value):存储元素
(3):删除数据:
clear():移出所有元素.
Object remove(Object key):根据指定的键删除元素.
(4):判断:
boolean containsKey(Object key)如果此映射包含指定键的映射关系,则返回true.
boolean containsValue(Object value)如果此映射将一个或多个键映射到指定值,则返回true.
boolean isEmpty():判断是否为空.
(5):int size():获取Map的键值对的个数.
4:如何遍历Map:
单独使用Map的键或值的集合的时候,可以分别使用:keySet和value方法
真正意义上的遍历,有两种方式:
第一种:
思路:
先获取键的集合.Set<K> keySet():返回键的Set集合.得到所有的键.
遍历键的集合,获取到每一个键值.Collection<V> values(); 返回的就是值的Collection集合.
根据每一个键值,调用Map的get方法,获取每一个键值对应的值
第二种:
Set<Map.Entry<K,V>> entrySet()
思路:先获取键值对对象的集合.
遍历这个对象的集合.
根据遍历的每一个对象,获取键和值.
举例: 先获取夫妻的结婚证的集合.
遍历这个集合,获取到每一张结婚证.
按照结婚证上的名字获取每一个丈夫和妻子.
例:
public class MapDemo {
public static void main(String[] args) {
HashMap<String,Student> hmp=new HashMap<String,Student>();
hmp.put("001", new Student("张三",29));
hmp.put("004", new Student("赵六",23));
hmp.put("003", new Student("网速",12));
hmp.put("002", new Student("李四",30));
hmp.put("005", new Student("钱起",56));
//第一种方法:
/*Set<String> keySets = hmp.keySet();
Iterator<String> it3 = keySets.iterator();
while(it3.hasNext()){
String key = it3.next();
Student value = hmp.get(key);
System.out.println(key+"***"+value);
}
System.out.println("*************************");
*/
//第二种方法:
Set<Map.Entry<String,Student>> setmp=hmp.entrySet();
for(Iterator<Map.Entry<String,Student>> it=setmp.iterator();it.hasNext();){
Map.Entry<String,Student> mape=it.next();
String s=mape.getKey();
Student stu=mape.getValue();
System.out.println(s+"..."+stu.getName()+"....."+stu.getAge());
}
}
}
class Student {
private String name;
private int age;
public Student(){}
public Student(String name,int age){
this.name=name;
this.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;
}
}
5:HashMap
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键
此实现不是同步的
例:保证元素的唯一性:
public class HashMap_保证元素的唯一性 {
public static void main(String[] args) {
HashMap<String,Integer> hm=new HashMap<String,Integer>();
hm.put("张三", 23);
hm.put("李四", 24);
hm.put("王五", 39);
hm.put("朱丽叶", 19);
hm.put("梁山泊", 23);
hm.put("王五", 39);
Set<String> set=hm.keySet();
for(Iterator<String> it=set.iterator();it.hasNext();){
String key=it.next(); //获取键
Integer value=hm.get(key); //获取值
System.out.println(key+"....."+value);
}
}
}
class Stu {
private String name;
private int age;
public Stu(){}
public Stu(String name,int age){
this.name=name;
this.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;
}
public boolean equals(Object obj){ //覆写equals方法
if(this==obj){
return true;
}
if(!(obj instanceof Stu)){
return false;
}
Stu s=(Stu)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
public int hashCode(){ //覆写hashCode方法
return this.name.hashCode()+this.age*17;
}
}
例2:HashMap的嵌套:
/*
传智播客:
jc|基础班
001 张三
002 李四
jy|就业班
001 王五
002 赵六
分析:
1:在大集合中嵌套小集合
3:传智播客是一个大集合
4:基础班和就业班又是一个集合.
5:在小集合中学号为键,Student对象为值.
*/
public class HashMap_集合嵌套 {
public static void main(String[] args) {
HashMap<String,HashMap<String,String>> hm=new HashMap<String,HashMap<String,String>>(); //大集合
HashMap<String,String> hm1=new HashMap<String,String>(); //小集合基础班
hm1.put("001", "张三");
hm1.put("002", "李四");
HashMap<String,String> hm2=new HashMap<String,String>(); //小集合就业班
hm2.put("001", "王五");
hm2.put("002", "赵六");
hm.put("基础班",hm1);
hm.put("就业班",hm2);
Set<String> set=hm.keySet();
for(Iterator<String> it=set.iterator();it.hasNext();){
String str1=it.next(); //取得大集合的键
HashMap<String,String> hp=hm.get(str1); //取得大集合的值
System.out.println(str1);
Set<String> ss=hp.keySet(); //得到小集合的所有键
for(Iterator<String> itt=ss.iterator();itt.hasNext();){
String str2=itt.next(); //取得小集合的键
String str3=hp.get(str2); //取得小集合的值
System.out.println("\t"+str2+"....."+str3);
}
}
}
}
6:TreeMap:
基于二叉树实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,
具体取决于使用的构造方法。
例:
1:按照年龄排序,如果年龄相同按姓名排,让元素本身具有比较性实现Comparable接口
2:根据名字的长度排序,并且让集合本身具有比较性.
*/
public class TreeMap_保证元素的有序性 {
public static void main(String[] args) {
//内部类方式
/* TreeMap<Person,String> tmp=new TreeMap<Person,String>(new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int num=p1.getAge()-p2.getAge();
int num1=p1.getName().compareTo(p2.getName());
return num==0?num1:num;
}
});*/
//使用比较器,让集合具备比较性
TreeMap<Person,String> tmp=new TreeMap<Person,String>(new ComImp());
//让元素自身具有比较性
//TreeMap<Person,String> tmp=new TreeMap<Person,String>();
tmp.put(new Person("ly刘亦菲",22),"001");
tmp.put(new Person("ls刘诗诗", 2),"002");
tmp.put(new Person("杨幂",30),"003");
tmp.put(new Person("李冰冰",25),"004");
Set<Person> set=tmp.keySet();
for(Iterator<Person> it=set.iterator();it.hasNext();){
Person key=it.next();
String value=tmp.get(key);
System.out.println(key.getName()+"....."+key.getAge()+"..."+value);
}
}
}
class Person implements Comparable<Person> { //让元素自身具有比较性
private String name;
private int age;
public Person(){}
public Person(String name,int age){
this.name=name;
this.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;
}
@Override
public int compareTo(Person p) {
int num=this.age-p.age;
int num1=this.name.compareTo(p.name);
return num==0?num1:num;
}
}
class ComImp implements Comparator<Person>{
@Override
public int compare(Person p1, Person p2) {
int num=p1.getAge()-p2.getAge();
int num1=p1.getName().compareTo(p2.getName());
return num==0?num1:num;
}
}
7:Collections: Collection的工具类.
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。
排序: sort();
二分查找: binarySearch();
反转: reverse();
8:Arrays: 数组操作的工具类.
toString(基本数据类型[])把数组用字符串输出.
sort();排序
binarySearch();二分查找.
9:增强for循环:
格式:
for(元素的数据类型 变量名:数组或Collection集合)
{
执行语句;
}
好处:
简化了对数组,集合的遍历.
例:for(int x:arr){
System.out.println(x);//自动从数组arr中的0索引出开始,获取每一个值赋给x.
}
10:方法的另一种形式:可变参数方法
返回值类型 函数名(数据类型... 数组名){}
注意:假如有多个参数的时候,而且你的参数有可变参数,这个时候,可变参数必须置于方法参数的最后边.
例: int run(int b,int...a){}
11:静态导入:
import默认导入是导入到类级别.
而静态导入是导入到方法的级别.
格式:
import static 类名.方法;
相关文章推荐
- 【Java学习笔记】正则表达式·集合和列表
- Java基础知识强化之集合框架笔记50:Map集合之Map集合的概述和特点
- Java基础知识强化之集合框架笔记59:Map集合之TreeMap(TreeMap<String,String>)的案例
- Java集合源码阅读笔记-HashSet
- Java基础知识强化之集合框架笔记67:Map集合面试题之List,Set,Map等接口是否继承自Map接口
- JAVA笔记--集合框架
- Java笔记4 JavaAPI<4>集合(Arrays)、Collections
- JAVA学习笔记——Set集合
- Java学习笔记【集合】
- Java基础知识强化之集合框架笔记77:ConcurrentHashMap之 ConcurrentHashMap的基本操作
- java笔记(六):集合,容器
- 学习笔记 java 集合(三)
- java毕向东听课笔记27(集合框架-Map)
- java学习笔记11--集合总结
- java笔记-集合框架-集合排序
- 黑马程序员——java集合学习笔记
- java笔记1:数组与集合
- JAVA核心技术学习笔记(第七版,Ⅱ高级特性之集合)
- 笔记整理(java基础十----集合)
- 06-java学习笔记-集合框架