------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
四、集合
1. 集合概述
集合类的出现:面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
对象多了用集合存,数据多了用对象存。
数组和集合的区别:
1.数组是固定长度,集合是可变长度。
2.数组存储对象的时候只能存储同一种类型的对象。
3.数组可以存储基本数据类型,集合只能存储对象。
集合的特点:
1.用于存储对象的容器;2.集合的长度是可变的;3.集合中不可以存储基本数据类型值;
4.集合中存放的不是对象实体,是对象的地址值
集合框架:
集合容器因为内部的数据结构不同,有多种具体容器,不断的向上抽取,就形成了集合框架。
大的框架可以分为Collection和Map两类,Collection包括List和Set集合,List包括ArrayList和LinkedList,Set包括HashSet和TreeSet,Map包括HashMap和TreeMap集合
Collection的常见方法:
1.添加
boolean add(Object obj)
2.删除
boolean remove(object obj)
boolean removeAll(Collection coll);
3.判断
boolean contains(object obj)
boolean containsAll(Colllection coll);
boolean isEmpty():判断集合中是否有元素。
4.获取
int size()
取出元素的方式:迭代器。
该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在容器中进行内部实现的。对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可,也就是iterator方法。Iterator接口就是对所有的Collection容器进行元素取出的公共接口。其实就是抓娃娃游戏机中的夹子!
5.其他:
boolean retainAll(Collection coll);取交集。
Object[] toArray():将集合转成数组。
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),元素可以重复。
|--Set:元素不能重复,无序。List:特有的常见方法:有一个共性特点就是都可以操作角标。
1,添加
void add(index,element);
void add(index,collection);
2,删除;
Object remove(index):
3,修改:
Object set(index,element);
4,获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);
list集合是可以完成对元素的增删改查。
List
|--Vector:内部是数组数据结构,是同步的。增删,查询都很慢!
|--ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。
|--LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。
Set:元素不可以重复,是无序。
Set接口中的方法和Collection一致。
|--HashSet: 内部数据结构是哈希表 ,是不同步的。
如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true。
如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。
一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。
建立对象判断是否相同的依据。
|--TreeSet:可以对Set集合中的元素进行排序。是不同步的。
判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
TreeSet对元素进行排序的方式一:
让元素自身具备比较功能,元就需要实现Comparable接口。覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
>将该类对象作为参数传递给TreeSet集合的构造函数。
哈希表确定元素是否相同
1,判断的是两个元素的哈希值是否相同。
如果相同,在判断两个对象的内容是否相同。
2,判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals。
Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实map集合中存储的就是键值对。
map集合中必须保证键的唯一性。 常用方法:1,添加。
value put(key,value):返回前一个和key关联的值,如果没有返回null.2,删除。
void clear():清空map集合。
value remove(key):根据指定的key翻出这个键值对。 3,判断。
>boolean containsKey(key):
boolean containsValue(value):
boolean isEmpty();4,获取。
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键。
int size(): 获取键值对的个数。 Map常用的子类:
|--Hashtable :内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap : 内部结构是哈希表,不是同步的。允许null作为键,null作为值。
|--TreeMap : 内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。
import java.util.*;
/*
创建集合
1,add方法的参数类型是Object,以便接收任意类型的对象
2,集合中存储的都是对象的引用(地址)
迭代器:
几何元素的取出方式。
把取出方式定义在集合的内部,
这样取出方式就可以直接访问集合内部的元素。
那么取出方式就被定义成了内部类。
而每一个容器的数据结构不同,所以取出的动作细节也不一样,但都有共性内容,判断和取出
那么可以将共性抽取。
这些内部类都符合一个规则,该规则即为Iterator接口
通过集合的iterator方法可以获取到迭代器对象。
*/
class CollectionDemo
{
public static void main(String[] args)
{
//method_1();
//method_2();
method_3();
}
public static void method_3()
{
ArrayList al1 = new ArrayList();
al1.add("java01");
al1.add("java02");
al1.add("java03");
al1.add("java04");
Iterator it = al1.iterator(); //获取迭代器用于取出集合中的元素
while (it.hasNext())
{
sop(it.next());
}
/*
迭代元素的for循环写法
for(Iterator it = al.iterator();it.hasNext();)
{
sop(it.next());
}
*/
}
public static void method_2()
{
ArrayList al1 = new ArrayList();
al1.add("java01");
al1.add("java02");
al1.add("java03");
al1.add("java04");
ArrayList al2 = new ArrayList();
al2.add("java01");
al2.add("java02");
al2.add("java05");
al2.add("java06");
//al1.retainAll(al2); //取交集,al1只会保留与al2相同的部分,打印结果:[java01,java02]
//al1.removeAll(al2); //al1移除与al2交集部分,打印结果:[java03,java04]
sop(al1);
sop(al2);
}
public static void method_1()
{
//创建一个集合容器,使用Collection接口的子类,ArrayList
ArrayList al = new ArrayList();
//1,添加元素
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
//打印集合
sop("原集合"+al);
//3,删除元素
al.remove("java02");
//2,获取集合长度
sop("size::"+al.size());
//清空集合
//al.clear();
//4,判断元素是否存在
sop(al.contains("java01"));
//判断是否为空
sop(al.isEmpty());
//打印改变后的集合
sop(al);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
2. List集合
/*
List:
特有方法。凡是可以操作角标的方法都是该体系特有的方法。
增
add(index,element);
addAll(index,Collection);
删
remove(index);
改(list特有)
set(index,element);
查
get(index);
subList(from,to);
listIterator();
*/
import java.util.*;
class ListDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList a1 = new ArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
a1.add("java04");
a1.add("java05");
ListIterator li = a1.listIterator();//列表迭代器
while(li.hasNext())
{
Object obj = li.next();
if(obj.equals("java02"))
li.add("java009");
sop(obj);
}
}
public void h1()
{
ArrayList a1 = new ArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java03");
a1.add("java04");
a1.add("java05");
sop("元集合是:"+a1);
a1.add(1,"java09");//添加指定位置元素
sop(a1);
a1.remove(2);//删除指定位置元素
sop(a1);
a1.set(2,"java007");//修改
sop(a1);
sop(a1.get(3));//取值
for(int x=0;x<a1.size();x++)//遍历
{
sop(a1.get(x));
}
//通过indexof()获取对象位置
sop(a1.indexOf("java05"));
List sub = a1.subList(1,3);
sop(sub);
}
}
List集合特有的迭代器ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常。
所以在迭代时,需要用到列表迭代器实现在遍历时的对List集合的操作
3. Vector
import java.util.*;
/*
枚举就是vector特有的取出方式。
发现枚举和迭代器很像。
其实枚举和迭代是一样的。
因为枚举的名称和方法名都过长,
所以被迭代器取代了,
所以枚举就不用了。
*/
class VectorDemo
{
public static void main(String[] args)
{
Vector v = new Vector();
v.add("java01");
v.add("java04");
v.add("java03");
v.add("java02");
Enumeration en = v.elements();
while (en.hasMoreElements())
{
System.out.println(en.nextElements());
}
}
}
4. LinkedList
import java.util.*;
/*
LinkList:特有方法
addFirst();
addLast();
getFirst();
getLast();
获取元素,但不删除元素,如果集合中没有元素,会抛出oSuchElementException异常
removeFirst();
removeLast();
获取元素,但是元素被删除。如果集合没有元素,会抛出NoSuchElementException异常
JDK1.6中出现的替代方法:
offerFirst();
offerLast();
peekFirst();
peekLast();
获取元素,但不删除元素。如果集合没有元素,返回null
pollFirst();
pollLast();
获取元素,但是元素被删除。如果集合中没有元素,返回null。
*/
class LinkedListDemo
{
public static void main(String[] args)
{
LinkedList link = new LinkedList();
link.addFirst("java01");
link.addLast("java02");
link.addFirst("java03");
link.addLast("java04");
sop(link);
sop(link.getFirst());
sop(link.getLast());
sop(link.removeFirst());
sop(link.size());
while(!link.isEmpty())
{
sop(link.removeFirst());
}
}
public static void sop(Object o)
{
System.out.println(o);
}
}
import java.util.*;
/*
使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出 如同杯子
队列:先进先出 如同管道
*/
class DuiLie
{
private LinkedList link;
DuiLie()
{
link = new LinkedList();
}
public void myAdd(Object obj)
{
link.addFirst(obj);
}
public Object myGet()
{
link.removeLast();
}
public boolean isNull()
{
return link.isEmpty();
}
}
class LinkedListTest
{
public static void main(String[] args)
{
DuiLie d = new DuiLie();
d.myAdd("java01");
d.myAdd("java03");
d.myAdd("java02");
while(!d.isNull)
{
System.out.println(d.myGet());
}
}
}
5. ArrayList
/*
定义一个功能,传进来一个ArrayList,返回一个没有重复元素的
ArrayList
*/
import java.util.*;
class ALUtil
{
private boolean flag = false; //标记用于标记传入list元素和返回newlist元素是否相同
ArrayList list = new ArrayList(); //传入集合
ArrayList newlist = new ArrayList(); //返回集合
ALUtil(ArrayList list)
{
this.list = list; //构造函数接收传入数据
}
public ArrayList getNewArrayList()
{
newlist.add(list.get(0)); //先将传入集合的第一个元素添加
for (int x=1;x<list.size() ;x++ ) //外循环控制传入集合角标
{
for (int y=0;y<newlist.size() ;y++ ) //内循环控制返回集合角标
{
if ((list.get(x)).equals(newlist.get(y))) //如果返回集合中有和传入集合中相同元素,标记改为真
flag = true;
}
if (flag==false) //判断标记,如果为假说明遍历到了不重复元素,那么就存入新集合
{
newlist.add(list.get(x));
}
else //如果标记为真,就把标记改为假,不做存入动作
flag = false;
}
return newlist;
}
}
class ALUtilDemo
{
public static void main(String[] args)
{
ArrayList al1 = new ArrayList();
al1.add("0");
al1.add("0");
al1.add("1");
al1.add("0");
al1.add("1");
al1.add("2");
System.out.println(al1.get(0).equals(al1.get(1)));
ArrayList al = new ALUtil(al1).getNewArrayList();
System.out.println(al);
}
}
/*
定义一个功能,传进来一个ArrayList,返回一个没有重复元素的
ArrayList
*/
import java.util.*;
class ALUtil
{
private boolean flag = false; //标记用于标记传入list元素和返回newlist元素是否相同
ArrayList list = new ArrayList(); //传入集合
ArrayList newlist = new ArrayList(); //返回集合
ALUtil(ArrayList list)
{
this.list = list; //构造函数接收传入数据
}
public ArrayList getNewArrayList()
{
Iterator it = list.iterator();
while (it.hasNext())
{
Object o = it.next();
if(!newlist.contains(o))
newlist.add(o);
}
return newlist;
}
}
class ALUtilDemo
{
public static void main(String[] args)
{
ArrayList al1 = new ArrayList();
al1.add("0");
al1.add("0");
al1.add("1");
al1.add("0");
al1.add("1");
al1.add("2");
ArrayList al = new ALUtil(al1).getNewArrayList();
System.out.println(al);
}
}
import java.util.*;
/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素。
比如:存入人对象。同姓名同年龄,视为同一个人,为重复元素。
*/
//定义Person类,内含对象的基本方法
class Person
{
String name;
int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public void print()
{
System.out.println(this.name+"::"+this.age);
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
//建立集合工具类,用于将传进来的集合转为无重复集合,但仅限于对象为Person的集合
class ArrUtil
{
ArrayList list = new ArrayList();
ArrayList newlist = new ArrayList();
//构造函数接收集合
ArrUtil(ArrayList list)
{
this.list = list;
}
public ArrayList getArr()
{
Iterator it = list.iterator();
while (it.hasNext())
{
Object o = it.next();
//判断从传入集合取出对象是否为Person对象
if (o instanceof Person)
{
Person p = (Person)o;
//调用自定义方法来判断临时集合中是否包含与遍历到对象
//相同的对象(通过姓名和年龄判断)
//如果不包含,则添加元素
if (!this.contains(p))
{
newlist.add(p);
}
else
System.out.println("不是Person对象");
}
}
return newlist;
}
//自定义contains方法用于判断临时集合是否包含与传入对象相同的对象
//通过Person类的name和age判断
public boolean contains(Person p)
{
//定义标记,false表示不相同
boolean flag = false;
Iterator it = newlist.iterator();
while (it.hasNext())
{
Person p1 = (Person)it.next();
if (p1.getName()==p.getName())
{
if (p1.getAge()==p.getAge())
{
flag = true;
}
}
}
return flag;
}
}
class ListDemo
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("zhangsan",21));
al.add(new Person("lisi",22));
al.add(new Person("wangwu",21));
al.add(new Person("zhangsan",21));
ArrayList al1 =new ArrUtil(al).getArr();
Iterator it =al1.iterator();
while (it.hasNext())
{
Person p = (Person)it.next();
System.out.println(p.getName()+"::"+p.getAge());
}
}
}
6. HasSet
import java.util.*;
/*
往hashset中存入自定对象
姓名和年龄相同为同一个人,重复元素
HashSet是如何保证元素的唯一性的呢?
是通过HashCode和equals来完成的
如果元素的HashCode值相同,才会判断equals是否为true。
如果元素HashCode值不同,不会调用equals.
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
*/
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");
return name.hashCode()+age;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println("equals run");
return this.name.equals(p.name) && this.age == p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashSetTest
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
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));
sop(hs.contains(new Person("a1",11)));
sop(hs.remove(new Person("a3",13)));
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"......"+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
import java.util.*;
/*
往hashset中存入自定对象
姓名和年龄相同为同一个人,重复元素
*/
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;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class HashSetTest
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add(new Person("a1",11));
hs.add(new Person("a2",12));
hs.add(new Person("a3",13));
hs.add(new Person("a4",14));
Iterator it = hs.iterator();
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"......"+p.getAge();)
}
}
}
7. TreeSet
Set:无序,不可重复元素
|--HashSet:数据结构是哈希表,线程是非同步的。
保证元素唯一性原理,判断元素的HashCode是否相同,如果相同
还会继续判断equals方法,是否为true
|--TreeSet:可以对set集合中的元素排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return0;
TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现
comparable接口,覆盖compareTo方法
TreeSet的第二种排序方式
当元素自身不具备比较性时,或者具备的比较性不是需要的,
这是需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
import java.util.*;
/*
需求:
往TreeSet集合中存储自定义对象学生。
想按照学生的年龄排序。
*/
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi08",19));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student p = (Student)it.next();
sop(p.getName()+"........."+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class Student implements Comparable//该接口强制让学生具备比较性
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj;
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
import java.util.*;
/*
当元素自身不具备比较性时,或者比较性不是所需要的。这时
需要让容器自身具备比较性
定义了一个比较器,将比较器对象作为参数传递给treeset集合的构造函数
*/
class TreeSetDemo2
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new MyCompare());
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi007",29));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi08",19));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student p = (Student)it.next();
sop(p.getName()+"........."+p.getAge());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class Student implements Comparable//该接口强制让学生具备比较性
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int compareTo(Object obj)
{
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj;
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class MyCompare implements Comparator
{
public int compare(Object o1,Object o2)
{
Student s1 = (Student)o1;
Student s2 = (Student)o2;
int num = s1.getName().compareTo(s2.getName());
if(num==0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
return num;
}
}
/*
练习:按照字符串长度排序。
字符串本身具备比较性,但是他的比较方式不是所需要的
这时就只能使用比较器。
*/
import java.util.*;
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StrLenComparator());
ts.add("asd");
ts.add("kjsahdkj");
ts.add("kjsa");
ts.add("kjsgf");
ts.add("we");
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class StrLenComparator implements Comparator
{
public int compare(Object o1,Object o2)
{
String s1 = (String)o1;
String s2 = (String)o2;
if(s1.length()>s2.length())
return 1;
if(s1.length()==s2.length())
return 0;
/*
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2);
return num;
*/
return -1;
}
}
8. 泛型
泛型:jdk1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制。
好处
1.将运行时期出现问题ClassCastException,转移到了编译时期
方便程序员解决问题,让运行时期问题减少,安全。
2.避免了强制转换的麻烦
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见,只要见到<>就要定义泛型
其实<>就是用来接收类型的,当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
import java.util.*;
class GenericDemo
{
public static void main(String[] args)
{
ArrayList<String> a1 = new ArrayList<String>();
a1.add("abc01");
a1.add("abc0991");
a1.add("abc014");
Iterator<String> it = a1.iterator();
while(it.hasNext())
{
String s = (String)it.next();
System.out.println(s.length());
}
}
}
import java.util.*;
class GenericDemo2
{
public static void main(String[] args)
{
TreeSet<String> ts = new TreeSet<String>(new LenComparator());
ts.add("abcd");
ts.add("abcde");
ts.add("abcdef");
ts.add("abcdefth");
Iterator<String> it = ts.iterator();
while(it.hasNext())
{ String s = it.next();
System.out.println(s);
}
}
}
class LenComparator implements Comparator<String>
{
public int compare(String o1,String o2)
{
int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));
if(num==0)
return o1.compareTo(o2);
return num;
}
}
//泛型定义在接口上
interface Inter<T>
{
void show(T t);
}
/*
class InterImpl implements Inter<String>
{
public void show(String t)
{
System.out.println("show:"+t);
}
}
*/
class InterImpl<T> implements Inter<T>
{
public void show(T t)
{
System.out.println("show:"+t);
}
}
class GenericDemo5
{
public static void main(String[] args)
{
//InterImpl i = new InterImpl();
//i.show("haha");
InterImpl<Integer> i = new InterImpl<Integer>();
i.show(4);
}
}
import java.util.*;
/*
? 通配符,也可以理解为占位符。
泛型的限定:
? extends E:可以接受E类型或者E的子类型,上限限定
? super E:可以接受E类型或者E的父类型,下限限定
*/
class GenericDemo6
{
public static void main(String[] args)
{
ArrayList<String> a1 = new ArrayList<String>();
a1.add("abcd1");
a1.add("abcd2");
a1.add("abcd3");
ArrayList<Integer> a2 = new ArrayList<Integer>();
a2.add(4);
a2.add(7);
a2.add(1);
printColl(a1);
printColl(a2);
}
public static void printColl(ArrayList<?> a1)
{
Iterator<?> it = a1.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
9. Map
Map集合特点:
该集合存储键值对,一对一对往里存,而且要保证键的唯一性
1.添加
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2.删除
clear()
remove(Object key)
3.判断
containsKey(Object key)
containsValue(Object value)
isEmpty()
4.获取
get(Object key)
size()
values()
entrySet()
keySet()
Map ***
|--Hashtable:底层是哈希表数据结构,不可以传入null作为键,null作为值的情况,该集合是线程同步的jdk1.0
|--HashMap:底层是哈希表结构,允许使用null值和键,该集合是不同步的jdk1.2
|--TreeMap:底层是二叉树数据结构,线程不同步。可以用于给map集合中的键进行排序
和set很像
其实大家,set底层就是使用了map集合
import java.util.*;
class MapDemo
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
//添加元素时,如果出现相同的键,那后添加的值会覆盖原有键对应的值
//put方法会返回原来的值
sop("map:"+map.put("01","zhangsan1"));
map.put("02","zhangsan2");
map.put("03","zhangsan3");
sop("containsKey:"+map.containsKey("02"));
sop("get:"+map.get("023"));
map.put(null,"zhangsan4");
sop("get:"+map.get(null));
//可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断
//获取map集合中所有的值
Collection<String> coll = map.values();
sop(coll);
sop(map);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
map集合的两种取出方式:
1.keySet:将map中的所有的键存入到set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值。
map集合的取出原理:将map集合转成set集合,再用迭代器取出
2.Set<Map.entry<k,v>> entrySet:将map集合中的映射关系取出
entrySet将map集合中的映射关系取出,这个关系为Map.Entry类型,
关系对象Map.Entry获取到后,就可以通过Map.Enter中的getKey和getValue方法获取关系中的键和值
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("02","zhangsan2");
map.put("01","zhangsan5");
map.put("04","zhangsan4");
map.put("03","zhangsan8");
//将map集合中的映射关系取出
Set<Map.Entry<String,String>> entrySet = map.entrySet();
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
while(it.hasNext())
{
Map.Entry<String,String> me = it.next();
sop(me.getKey()+me.getValue());
}
//先获取map集合的所有键的Set集合,keySet();
/* Set<String> keySet = map.keySet();
//有了Set集合就可以获取迭代器了
Iterator<String> it = keySet.iterator();
while(it.hasNext())
{
String key = it.next();
String value = map.get(key);
sop(key+"......"+value);
}*/
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
import java.util.*;
/*
每一个学生都有对应的归属地
学生student,地址String
学生属性:姓名,年龄
注意:姓名年龄相同的视为同一个学生。
保证学生的唯一性
1.描述学生
2.定义map容器,将学生作为键,地址作为值,存入、
3.获取map集合中的元素
*/
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)//假如我新建一个Student("zhangsan","20")对象,那this.name不就是zhangsan了么
// 那这里这个比较为何会拿以前的所有name都比一次?
{
int num = new Integer(this.age).compareTo(new Integer(s.age));
if (num==0)
return this.name.compareTo(s.name);
return num;
}
public int hasCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+":"+age;
}
}
class MapTest
{
public static void main(String[] args)
{
Map<Student,String> hm = new HashMap<Student,String>();
hm.put(new Student("lisi1",21),"beijing");
hm.put(new Student("lisi2",22),"shanghai");
hm.put(new Student("lisi3",23),"shenzhen");
//第一种取出方式
Set<Student> keySet = hm.keySet();
Iterator<Student> it = keySet.iterator();
while(it.hasNext())
{
Student stu = it.next();
String addr = hm.get(stu);
sop(stu+"......."+addr);
}
//第二种取出方式
Set<Map.Entry<Student,String>> entrySet = hm.entrySet();
Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();
while(iter.hasNext())
{
Map.Entry<Student,String> me = iter.next();
Student stu = me.getKey();
String addr = me.getValue();
sop(stu+"..........."+addr);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
/*
需求:对学生的年龄进行升序排序
因为数据是以键值对形式存在的。
所以要使用可以排序的Map集合TreeMap
*/
import java.util.*;
class Student
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int hasCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+":"+age;
}
}
class StuNameComparator implements Comparator<Student> //姓名比较器
{
public int compare(Student s1,Student s2)
{
int num = s1.getName().compareTo(s2.getName());
if(num==0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
return num;
}
}
class StuAgeComparator implements Comparator<Student> //年龄比较器
{
public int compare(Student s1,Student s2)
{
int num = new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
if (num==0)
return s1.getName().compareTo(s2.getName());
return num;
}
}
class MapTest2
{
public static void main(String[] args)
{
//Scanner sc = new Scanner(System.in);
//sop("请选择排序方式:1.按年龄排序 2.按姓名排序");
//Integer s = sc.nextInt();
TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());
tm.put(new Student("lisi1",45),"beijing");
tm.put(new Student("lisi2",21),"shanghai");
tm.put(new Student("lisi3",25),"shenzhen");
tm.put(new Student("lisi8",18),"chaoyan");
tm.put(new Student("lisi4",33),"chengdu");
tm.put(new Student("lisi6",11),"wuhan");
Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
Iterator<Map.Entry<Student,String>> it = entrySet.iterator();
while(it.hasNext())
{
Map.Entry<Student,String> me = it.next();
Student stu = me.getKey();
String addr = me.getValue();
sop(stu+".............."+addr);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
import java.util.*;
class Maptest3
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
sop("请输入要判断的字符串:");
String s = sc.next();
TreeMap<String,Integer> hm =new TreeMap<String,Integer>();
for(int x=0;x<s.length();x++)
{
String str = String.valueOf(s.charAt(x));
if (hm.get(str)==null)
{
hm.put(str,1);
}
else
hm.put(str,(hm.get(str)+1));
}
Set<String> keySet = hm.keySet();
Iterator<String> it =keySet.iterator();
while(it.hasNext())
{
String str = it.next();
Integer i = hm.get(str);
sop(str+"("+String.valueOf(i)+")");
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class paixu implements Comparator<String>
{
public int compare(String s1,String s2)
{
return s2.compareTo(s1);
}
}
import java.util.*;
class Maptest
{
public static void main(String[] args)
{
TreeMap<String,TreeMap<String,String>> tm = new TreeMap<String,TreeMap<String,String>>();
TreeMap<String,String> tm1 =new TreeMap<String,String>();
tm1.put("01","zhangsan1");
tm1.put("02","zhangsan2");
tm1.put("03","zhangsan3");
TreeMap<String,String> tm2 =new TreeMap<String,String>();
tm2.put("01","zhangsan4");
tm2.put("02","zhangsan5");
tm2.put("03","zhangsan6");
tm.put("01",tm1);
tm.put("02",tm2);
Iterator<String> it = tm.keySet().iterator();
while(it.hasNext())
{
String str = it.next();
TreeMap<String,String> t = tm.get(str);
sop(str);
getStudentInfo(t);
}
}
public static void getStudentInfo(TreeMap<String,String> tm)
{
Iterator<String> it = tm.keySet().iterator();
while(it.hasNext())
{
String id = it.next();
String name = tm.get(id);
sop(id+"......."+name);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
10. 集合工具类
1.Collections
/*
集合框架的集合类。
Collections:
*/
import java.util.*;
class CollectionsDemo
{
public static void main(String[] args)
{
sortDemo();
maxDemo();
}
public static void binarySearchDemo()
{
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
Collections.sort(list);
int index = Collections.binarySearch(list,"aaa");//如果没有元素返回(-(插入点)-1)的数值
sop(index);
}
public static void maxDemo()
{
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("aaa");
list.add("zz");
list.add("kkkkk");
list.add("qq");
list.add("z");
sop(Collections.max(list,new StrLenComparator()));
}
public static void sortDemo()
{
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("aaa");
list.add("z");
list.add("kkkk");
list.add("qq");
sop(list); //打印结果:[abcd,aaa,z,kkkk,qq]
Collections.sort(list,new StrLenComparator());
sop(list); //打印结果:[aaa,abcd,kkkk,qq,z]
}
public static void sop(Object o)
{
System.out.println(o);
}
}
//按照字符串长度从小到大排序,长度相同按自然顺序排序
class StrLenComparator implements Comparator<String>
{
public int compare(String s1,String s2)
{
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
return s1.compareTo(s2);
}
}
import java.util.*;
class CollectionsDemo2
{
public static void main(String[] args)
{
fillDemo();
}
public static void fillDemo()
{
Scanner sc1 = new Scanner(System.in);
sop("请输入需要改变的起始位置的字符串");
String s1 = sc1.next();
Scanner sc2 = new Scanner(System.in);
sop("请输入需要改变的结束位置的字符串");
String s2 = sc2.next();
Scanner sc3 = new Scanner(System.in);
sop("请输入需要变成的字符串");
String s3 = sc3.next();
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
list.add("g");
list.add("h");
list.add("i");
list.add("j");
list.add("k");
list.add("l");
list.add("m");
list.add("n");
sop(list);
fill(list,s1,s2,s3);
sop(list);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void fill(List<String> list,String s,String f, String str)
{
if (list.indexOf(f)-list.indexOf(s)>=0 && !(list.indexOf(s)<0) && !(list.indexOf(f)<0))
{ int x = 0;
x = list.indexOf(s);
while(list.indexOf(f)-x>=0)
{
list.set(x,str);
x++;
}
}
else
throw new RuntimeException("list列表中没有包含"+s+"起始,或者"+f+"结尾的数据,请重新输入");
}
}
class com implements Comparator<String>
{
public int compare(String s1,String s2)
{
int num =new Integer(s1.length()).compareTo(new Integer(s2.length()));
if (num==0)
{
return s1.compareTo(s2);
}
return num;
}
}
import java.util.*;
class CollectionsDemo3
{
public static void main(String[] args)
{
shuffleDemo();
}
//随机排序
public static void shuffleDemo()
{
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("a");
list.add("s");
list.add("ddd");
list.add("zz");
sop(list);
Collections.shuffle(list);
sop(list);
}
//排序
public static void orderDemo()
{
TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());
ts.add("abcde");
ts.add("aaa");
ts.add("kkk");
ts.add("ccc");
Iterator it = ts.iterator();
while (it.hasNext())
{
System.out.println(it.next());
}
}
public static void sop(Object o)
{
System.out.println(o);
}
}
2.Arrays
用于操作数组的工具类
/*
数组工具类:
asList:将数组编程List集合
*/
import java.util.*;
class ArraysDemo
{
public static void main(String[] args)
{
//int[] arr {2,4,5};
//System.out.println(Array.toString(arr));
String[] arr = {"abc","cc","kkkk"};
List<String> list = Arrays.asList(arr);
//判断数组是否包含某个元素,将数组先转化为集合
//用集合的方法操作数组
//注意:将数组变成集合不可以使用集合的增删方法,因为数组的长度是固定的
//contain get indexOf subList
System.out.println(list.contains("cc"));
System.out.println(list);
int[] nums = {2,4,5};
//Integer[] num = {2,4,5};
List<int[]> li = Arrays.asList(nums);
//List<Integer> li = Arrays.asList(nums);
System.out.println(li);
/*
如果数组中的元素都是对象,那么变成集合时
数组中的元素就直接转换成集合中的元素
如果数组中的元素都是基本数据类型,
那么会将数组作为集合中的元素存在
*/
}
}
/*
集合变数组
*/
class CollectionToArray
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
/*
指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于集合的size,那么该方法内部
会创建一个新的数组。长度为集合的size
当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组
所以创建一个刚刚好的数组最优
为什么要将集合变数组?
为了限定对元素的操作。
*/
String[] arr = al.toArray(new String[0]);
System.out.println(Arrays.toString(arr));
}
}
11. JDK1.5新特性--高级for(ForEach)
import java.util.*;
/*
高级for循环
格式:
for(数据类型 变量名:被遍历的集合或者数组)
{
}
对集合进行遍历,只能获取元素,但不能对集合进行操作
迭代器除了遍历还可以进行remove集合中元素的动作
如果使用ListIterator,还可以在便利过程中对集合进行增删改查的动作
传统for和高级for有什么区别呢?
高级for有一个局限性,必须有被遍历的目标
建议在遍历数组的时候使用传统for,传统for可以定义角标
*/
class ForEachDemo
{
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
list.add("abc01");
list.add("abc02");
list.add("abc03");
Iterator<String> it = list.iterator();
while (it.hasNext())
{
System.out.println(it.next());
}
for (String s1:list )
{
System.out.println(s1);
}
int[] arr = {3,5,1};
for (int i : arr)
{
System.out.println(i);
}
HashMap<Integer,String> hm = new HashMap<Integer,String>();
hm.put(1,"abtc");
hm.put(2,"absc");
hm.put(3,"adbc");
hm.put(4,"abfc");
Iterator it1 = hm.keySet().iterator();
while (it1.hasNext())
{
Integer i = (Integer)it1.next();
System.out.println(i+"...."+hm.get(i));
}
for (Integer i : hm.keySet() )
{
System.out.println(i+"....."+hm.get(i));
}
Set<Map.Entry<Integer,String>> en = hm.entrySet();
for(Map.Entry<Integer,String> me : en)
{
System.out.println(me.getKey()+"....."+me.getValue());
}
}
}
12. JDK1.5新特性--可变参数
JDk1.5出现的新特性
可变参数其实就是上一种数组参数的简写形式,不用每一次都手动的建立数组对象。
只要将要操作的元素作为参数传递即可
隐式将这些参数封装成了数组
在使用时注意,可变参数一定要定义在参数列表的最后面
class ParamMethodDemo
{
public static void main(String[] args)
{
show(2,3,4);
}
public static void show(int...arr)
{
System.out.println(arr);
}
/* public static void show(int[] arr)
{
}
public void show(int a,int b)
{
System.out.println(a+","+b);
}
public void show(int a,int b,int c)
{
}
*/
}
13. JDK1.5新特性--静态导入
/*
StaticImport 静态导入
当类名重名时,需要指定具体的包名。
当方法重名时,指定具备所属的对象或者类。
*/
import static java.lang.System.*;
import java.util.*;
import static java.util.Arrays.*; //导入的是Arrays这个类中的所有静态成员
class StaticImport
{
public static void main(String[] args)
{
int[] arr = {3,1,5};
//Arrays.sort(arr);
sort(arr);
//int index = Arrays.binarySearch(arr,1);
int index = binarySearch(arr,1);
out.println(Arrays.toString());
}
}
14.API中的类System类
/*
System:
描述系统信息
获取系统信息:Properties getProperties();
*/
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
Properties prop = System.getProperties();
//因为properties是hashtable的子类,也就是map集合的一个子类对象
//那么可以通过map的方法取出该集合的元素
for (Object obj : prop.keySet())
{
String value = (String)prop.get(obj);
System.out.println(obj+"........."+value);
}
}
}
15. API中的类Runtime类
将java程序与其所在系统相连接的类,没有构造函数,不可以new对象,其方法都是静态的通过静态方法getRuntime方法返回本类对象
该类使用单例设计模式完成
class RuntimeDemo
{
public static void main(String[] args) throws Exception
{
Runtime r = Runtime.getRuntime();
Process p = r.exec("c:\\winmine.exe");
//Thread.sleep(4000);
//p.destroy();
Process p1 = r.exec("notepad.exe Demo.java");
}
}
16. Util包中的类Date类
日期格式化的类DateFormat是text包中的,因为最终要输出文本内容
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Date d = new Date();
System.out.println(d);
//将模式封装
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
//调用format方法格式化日期
System.out.println(sdf.format(d));
}
}
17. Util包中的类Calendar类
import java.util.*;
import java.text.*;
class CalendarDemo
{
public static void main(String[] args)
{
/*Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
System.out.println(sdf.format(d));*/
Calendar c = Calendar.getInstance();
//printCalendar(c);
//c.add(Calendar.DAY_OF_MONTH,18);
c.add(Calendar.DAY_OF_MONTH,-1);
printCalendar(c);
/*
Scanner sc = new Scanner(System.in);
sop("本程序可查询任意一年的二月有多少天,请输入要查询的年份");
String s = sc.next();
c.set(new Integer(s),1,28);
int num;
c.add(Calendar.DAY_OF_MONTH,1);
if (c.get(Calendar.DAY_OF_MONTH)==29)
{
num = 29;
}
else
num = 28;
sop(s+"年的二月有"+num+"天");*/
}
public static void printCalendar(Calendar c)
{
String[] mons = {"一月","二月","三月","四月"
,"五月","六月","七月","八月"
,"九月","十月","十一月","十二月"};
String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
int n1 = c.get(Calendar.MONTH);
int n2 = c.get(Calendar.DAY_OF_WEEK);
String year = c.get(Calendar.YEAR)+"年";
String month = mons[n1];
String day = c.get(Calendar.DAY_OF_MONTH)+"日";
String week = weeks[n2];
String hour = c.get(Calendar.HOUR_OF_DAY)+"时";
String minute = c.get(Calendar.MINUTE)+"分";
String second = c.get(Calendar.SECOND)+"秒";
sop(year+month+day+week+hour+minute+second);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
18. lang包中的Math类
<pre class="java" name="code">import java.util.*;
class MathDemo
{
public static void main(String[] args)
{
/*Random r = new Random();
for (int x=0;x<10 ;x++ )
{
//int f =(int)( Math.random()*10+1);
int d = r.nextInt(10)+1;
sop(d);
}*/
show();
}
public static void show()
{
double d = Math.ceil(12.34);
double d1 = Math.floor(12.34);
long d2 = Math.round(12.54);
sop("d="+d);
sop("d1="+d1);
sop("d2="+d2);
double d3 = Math.pow(2,3);
sop("d3="+d3); //结果:d=13.0,d1=12.0,d2=13,d3=8.0
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}