List类:有序,可重复–>有一些Collection类没有的方法,因为有脚标
* ArrayList
* LinkedList
* Vector
Set类:无序(存入和取出的顺序不一致),不可重复–>和Collection的方法一致
* HashSet
* TreeSet
1 使用LinkedList模拟堆数据结构和栈数据结构的存取操作过程
class Que
{
private LinkedList link = new LinkedList();
public void myAdd(Object obj){
link.addFirst(obj);
}
public Object myGet(){
return link.removeFirst();
}
public boolean isNull(){
return link.isEmpty();
}
public static void main(String[] args)
{
Que q = new Que();
q.myAdd("java01");
q.myAdd("java02");
q.myAdd("java03");
q.myAdd("java04");
while(!q.isNull())
{
System.out.println(q.myGet());
}
}
}
2 集合类的遍历:
1 使用Iterator迭代器遍历:
实现过程:
ArryList al = new ArryList();
al.add(obj);
for(Iterator it = al.iterator();it.hasNext();){
it.next();
}
底层实现,内部类
class ArrayList{
//ArrayList集合中有多个对象,存放的是它们的引用o1,o2,o3;
Object o1 = new Object():
Object o2 = new Object():
Object o3 = new Object():
class Itr implements Iterator //内部类实现Iterator接口
{
hasNext();
next();
remove();//方法。。。
}
public Iterator iterator(){
new Itr();
}
}
注意在使用对象传递时的安全问题(存入集合中元素均视为Object类型,通常都有向上转型的操作):
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("张洪题",28));//ArrayList类的方法add()定义为:boolean add(Object obj),因此,这一步做的动作相当于Object obj = new Person();存在向上转型
al.add(new Person("徐尚",27));
al.add(new Person("蒋晨晨",25));
Iterator i = al.iterator();
while (i.hasNext())
{
Person p = (Person)i.next();//如果直接使用i.next().getName();其中i.next()指的是Object类的对象,而Object类是没有getName()方法的,要想使用Person类的方法,必须向下转型
System.out.println(p.getName()+"---"+p.getAge()+"岁");
}
}
}
2 ListIterator
在Iterator遍历过程中,不能使用集合方法对元素进行增删操作,而Iterator只提供了hasNext(),next(),remove();三种方法,因此对于元素有脚标的ArryList集合,遍历时使用ListIterator迭代器;
3 在集合中存入实际对象
List集合,判断其中元素是否相同,使用的是equals()方法:
1. Object类的equals()方法:比较对象地址值;
2. String类的equals()方法:也是比较对象的地址值,因此对于String str1 = new String(“abc”)和String str2 = new String(“abc”),使用equals()方法将返回false;
3. 实际开发中,经常重写equals()方法(权限public):下面这个例子必须会写!
4. List集合中的contains();remove();方法底层都调用了equals();方法!!
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
String getName(){
return name;
}
int getAge(){
return age;
}
//该equals方法,在e.contains(o)方法使用时才能被隐式调用!-->o==null?e==null : o.equals(e)
public boolean equals(Object obj){//因为Object类中equals方法是public修饰,为了重写该方法,权限必须覆盖
if (!(obj instanceof Person))
{
return false;//此处应该使用try catch抛出异常;
}
Person p = (Person)obj;//向下转型
return name==p.getName() && age==p.getAge();
}
}
class EqualsDemo
{
public static ArrayList singleElement(ArrayList al){
//创建一个新的ArrayList集合用于存储单一元素
ArrayList newAl = new ArrayList();
Iterator i = al.iterator();
while (i.hasNext())
{
Object obj = i.next();
if(!newAl.contains(obj)){//contains方法,底层实现也是使用Object类的equals方法;
newAl.add(obj);
}
}
return newAl;
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
//其中放入相同的用户,要求剔除
//思路:创建一个静态方法,用于比较ArrayList中存放的Object类的具体值是否相同,需要重写所存储对象所属类的equals方法;
al.add(new Person("Zhang Hongti",28));
al.add(new Person("Xu Shang",27));
al.add(new Person("Jiang Chenchen",25));
al.add(new Person("Xu Shang",27));
al=singleElement(al);
Iterator i = al.iterator();
while(i.hasNext()){
Person p = (Person)i.next();
System.out.println(p.getName()+"---"+p.getAge());
}
}
}
4 HashSet
4.1 在HashSet中存入对象
- 不是按照你的存入顺序,而是按照对象的哈希值
- HashSet中存放对象引用的哈希值可以相同,这种情况下,会进一步比较是否属于同一个对象,从而确定要不要再集合中放入两个元素;
- 也就是说,判断是否在HashSet集合中加入一个不重复元素的步骤是:
- 调用hashCode()方法判断哈希值是否相同,不同则直接存入;
- 调用equals()方法继续判断,返回false则存入;
- **注意:**hashCode()和equals()方法常常需要被改写!不需要调用,使用集合Set类方法的时候从底层隐式调用的;
package com.cityu.collection;
class Demo{
//重写Object类的hashCode()方法
public int hashCode(Object obj){
return 199;
}
}
public class HashSet {
public static void main(String[] agrs){
Demo d1 = new Demo();
Demo d2 = new Demo();
System.out.println(d1);//底层调用Object类的toString()方法getClass().getName()+"@"+Integer.toHexString(hashCode());
System.out.println(d2);
}
}
5 TreeSet
- 底层数据结构是二叉树,保证数据唯一性的依据是compareTo方法return 0;
- 可以通过让对象所属类实现Comparable接口改写compareTo方法实现特定的排序方式;
- 定义一个比较器
/*
*在TreeSet集合中存入自定义对象,希望按照年龄进行排序
*
* */
package com.cityu.collection;
import java.util.*;
public class TreeSetDemo {
public static void main(String[] agrs){
TreeSet ts = new TreeSet();
ts.add(new Student("Zhang Hongti01", 23));
ts.add(new Student("Zhang Hongti03", 19));
ts.add(new Student("Zhang Hongti04", 19));//在主要条件相同的情况下,再去对比下一个条件,否则,会被当做相同元素无法存入集合
ts.add(new Student("Zhang Hongti05", 40));//向TreeSet中存入的对象必须实现Comparable接口,也就是该对象必须可以进行自然排序
for(Iterator i = ts.iterator();i.hasNext();){
Student s = (Student)i.next();
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
class Student implements Comparable
{
private String name;
private int age;
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public int compareTo(Object obj){
if(!(obj instanceof Student))
throw new RuntimeException("Wrong Class!");
Student str = (Student)obj;
if(this.age>str.age)
return 1;
if(this.age==str.age){
return this.name.compareTo(str.name);//字符串本身具有比较性,实现了Comparable接口
}
return -1;
}
}
使用定义比较器的方式使用自定义方法排序,必须会写!
/*
* 使用TreeSet集合对存入其中的字符串,按照其长度排序输出:
* 使用两种方法:
* 1. 让字符串对象实现Comparable接口,并重写compareTo()方法;
* 2. 让TreeSet容器自身具备比较性:定义一个比较器,在构造容器时,初始化该比较器;
* 对比着两种方法:常用的是使用比较器
* */
package com.cityu.collection;
import java.util.*;
class SetCompare implements Comparator
{
public int compare(Object o1,Object o2){
String str1 = (String)o1;
String str2 = (String)o2;
int num = str1.length()-str2.length();
if(num==0){
return str1.compareTo(str2);
}
return num;
}
}
public class TreeSetTest {
public static void main(String[] agrs){
TreeSet ts = new TreeSet(new SetCompare());
ts.add("abcd");
ts.add("abe");
ts.add("abcdef");
ts.add("efcd");
ts.add("bfcd");
for(Iterator i = ts.iterator();i.hasNext();){
String string = (String)i.next();
System.out.println(string);
}
}
}
6 Map集合
7. 集合框架的工具类
1. Collections类
2. Arrays类
- 用于操作数组的工具类
- asList()方法:
- 将数组变成List:好处是可以使用集合的思想和方法来操纵数组
class ArrayDemo{
public static void main(String[] agrs){
String[] arr = {"abd","cdb","ddd"};
List<String> list = Arrays.asList(arr);
System.out.println("arr:"+arr);
System.out.println("list:"+list);
System.out.println("contains:abd?"+list.contains("abd"));
}
}
输出:
arr:[Ljava.lang.String;@100363
list:[abd, cdb, ddd]
contains:abd?true
- 将List变成数组:是为了限制进一步对元素的操作(增删);
- 转换时,要确定数组大小:大了,补null;小了,创建新数组;最好是大小刚好:
ArrayList<String> al = new ArrayList<String>();
String[] arr = al.toArray(new String[al.size()]);
3. 迭代器接口(Iterable)
实现Iterable接口的类对象可以成为for-each循环的target:高等级for循环
for(数据类型 变量名:被遍历的集合(Collection)或者数组)
- 对集合遍历,只能获取元素,不能修改
ArrayList<String> al = new ArrayList<String>();
al.add("abd");
al.add("add");
al.add("fgh");
for(String s:al){
System.out.println(s);
}
for(String s:al){
s = "aa";
}
System.out.println(s);
输出:
abd
add
fgh
[abd, add, fgh]
- 因此,使用迭代器,可以使用remove元素的操作;
如果使用ListIterator,还可以遍历过程中进行增删改查操作;
Map集合不能使用,使用keySet()或者entrySet()获得Map中键的Set集合或者键值映射关系Set集合;
HashMap<Integer,String> hm = new HashMap<Integer,String>();
hm.put(1,"a");
hm.put(2,"b");
hm.put(3,"c");
Set<Map.Entry<Integer,String>> entrySet = hm.entrySet();
for(Map.Entry<Integer,String> me:entrySet){
System.out.println(me.getKey()+":"+me.getValue());
}
//或者简写为:
for(Map.Entry<Integer,String> me:hm.entrySet()){
System.out.println(me.getKey()+":"+me.getValue());
}
4. 可变参数
其实就是数组,不用每次都建立数组对象,只需要将要操作的元素作为参数即可,隐式地将这些元素封装成数组:
{ ...
varPara(2,3,4,5);
varPara(3,4,5,6,6,45)
public static void varPara(int... arr){
System.out.println(arr);
}
}
- 注意:可变参数一定要定义在参数列表的最后面,也就是说在可变参数后面不能继续定义参数
5. staticImport静态导入
对于全部都是静态方法的工具类
import static java.util.Arrays.*;
注意:如果方法重复(通常会和Object类的方法冲突)时,要明确所属类或者对象;
8 常见类:
1. System类:
没有构造函数,全是静态方法,一种工具类。
Properties类是HashTable子类,可以使用Map集合的方法;
System类的getProperties()静态方法,返回Properties子类;
import java.util.*;
public class SystemDemo {
public static void main(String[] agrs){
Properties prop = System.getProperties();
Set<Object> keySet = prop.keySet();
Iterator<Object> it = keySet.iterator();
while(it.hasNext()){
String value = (String)prop.get(it.next());
System.out.println(value);
}
//由于Set集合实现了Iterable接口,因此可以使用for-each高级循环
for(Object obj:prop.keySet()){
String value = (String)prop.get(obj);
System.out.println(value);
}
}
}
8.2 Runtime类
Runtime类同样没有构造函数,但是大多是非静态方法,如何调用?
- 使用getRuntime()静态方法,返回Runtime本类对象,就可以获得对象,从而调用该类方法;(单例设计模式,程序中只存在一个对象)
- Runtime类方法Process exec(String comand)
public class RuntimeDemo {
public static void main(String[] agrs) throws Exception
{
//Runtime r = Runtime.getRuntime();
//r.exec("C:\\Program Files\\Tencent\\QQ\\Bin\\QQ.exe");//因为“\”是转义字符
//杀死本程序启动的进程:无法杀平台进程,因为虚拟机无法拿到平台进程的对象p
Runtime r = Runtime.getRuntime();
Process p = r.exec("C:\\Program Files\\Tencent\\QQ\\Bin\\QQ.exe");//因为“\”是转义字符
Thread.sleep(4000);
p.destroy();
}
}
8.3 日期类Date
import java.text.*;//导包
class DateDemo{
public static void main(String[] agrs){
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/mm/dd");//创建一个模式对象
//使用该模式对象调用该类方法对日期对象格式化操作,返回字符串
String mydate = sdf.format(d);
System.out.println(mydate);
}
}
Calender类:获取修改时间,日期等(可以自定义格式)
* 0代表一月