9.集合类
特点:
1)对象封装数据,对象多了也需要存储。集合用于存储对象。
2)对象的个数确定可以使用数组,但是不确定怎么办?可以用集合。因为集合是可变长度的。
集合和数组的区别:
1)数组是固定长度的;集合可变长度的。
2)数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
3)数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。
对于集合容器,有很多种。因为每一个容器的自身特点不同,其实原理在于每个容器的内部数据结构(存储数据的方式)不同。
集合容器在不断向上抽取过程中。出现了集合体系。
9.1 共性方法
集合(collection)是接口,两个常见的子接口为List和Set
1)添加:
add(object): 添加一个元素
addAll(Collection) :添加一个集合中的所有元素。
2)删除:
clear(): 将集合中的元素全删除,清空集合。
remove(obj) : 删除集合中指定的对象。注意:删除成功,集合的长度会改变。
removeAll(collection) : 删除部分元素。部分元素和传入Collection一致。
3)判断:
boolean contains(obj) : 集合中是否包含指定元素 。
boolean containsAll(Collection) : 集合中是否包含指定的多个元素。
boolean isEmpty(): 集合中是否有元素。
4)获取:
int size():集合中有几个元素。
5)取交集:
boolean retainAll(Collection) :对当前集合中保留和指定集合中的相同的元素。如果两个集合元素相同,返回flase;如果retainAll修改了当前集合,返回true。
6)获取集合中所有元素:
Iterator iterator():迭代器
7)将集合变成数组:
toArray();
import java.util.*; //需要导入包
class CollectionDemo
{
public static void base_method()
{
//创建集合容器,使用Collection接口的子类ArrayList
ArrayList al = new ArrayList();
//添加元素
al.add("java01"); //add(Object obj);
al.add("java02");
al.add("java03");
al.add("java04");
//获取个数,集合长度
sop("size:"+al.size());
//打印集合
sop(al); //结果为[java01, java02, java03, java04]
//删除元素
al.remove("java02"); //删除后,长度也变短了
//清空集合
al.clear();
//判断元素
sop("java03是否存在:"+al.contains("java03"));
sop("集合是否为空"+al.isEmpty());
}
public static void method_2()
{
ArrayList al1 = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java03");
al.add("java04");
ArrayList al2 = new ArrayList();
al2.add("java01");
al2.add("java02");
al2.add("java05");
al2.add("java06");
al1.retainAll(al2); //取交集,al1中只会保留和al2中相同的元素
al1.removeAll(al2); //将al1中与al2中相同的元素去除
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
注意:
1)add方法的参数类型是object,以便于接收任意类型的对象
2)集合中存储的都是对象的引用(地址)
9.2 迭代器
迭代器(Iterator)是一个接口,是集合的取出元素的方式
| hasNext |
next | |
| remove |
每一个集合都有自己的数据结构,都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。
public static void method_get()
{
Collection coll = new ArrayList();
coll.add("java01");
coll.add("java02");
coll.add("java03");
coll.add("java04");
<span style="white-space:pre"> </span>//方式一
Iterator it = coll.iterator(); //调用集合实现类中的iterator()方法获取迭代器
while(it.hasNext()) //hasNext(),当仍有元素可以迭代,则返回true
{
sop(it.next());
}
<span style="white-space:pre"> </span>//方式二
for (Iterator it = coll.iterator();it.hasNext() ; ) //循环结束后对象it会释放,此代码更优
{
sop(it.next());
}
}
9.3 List接口
List接口是Collection接口的子类
List:元素是有序的,元素可以重复,因为该集合体系有索引
特有方法:凡是可以操作角标的方法都是该体系特有的方法(以ArrayList为例)
1) 增
add(index,element);
addAll(index,Collection);
2) 删
remove(index);
3) 改
set(index,element);
4) 查
get(index);
subList(from,to);
listIterator();
public static void method()
{
List list = new ArrayList();
//添加元素
list.add("java01");
list.add("java02");
list.add("java03");
//在指定位置添加元素
list.add(1,"java09"); //该index后的元素会向后顺延
//删除指定位置的元素
list.remove(2);
//修改元素
list.set(2,"java07");
//通过角标获取元素
list.get(1);
//获取所有元素
for (int x =0;x< list.size() ;x++ ) //集合子类用size()获取长度
{
System.out.println("list ("+")= "+ list.get(x));
}
Iterator it = list.iterator();
while(it.hasNext())
{
sop("next:"+it.next());
}
//通过indexOf获取对象的位置
sop("index="+ list.indexOf("java02"));
List sub = list.subList(1,3); //含头不含尾
}
List集合特有的迭代器:ListIterator是Iterator的子接口
在进行list列表迭代时,不可以通过集合对象的方法操作集合中的元素,比如添加新元素,因为会发生ConcurrentModificationException异常。
导致的原因是:集合引用和迭代器引用在同时操作元素,通过集合获取到对应的迭代器后,在迭代中,进行集合引用的元素添加,迭代器并不知道,所以会出现异常情况。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法时有限的,只能对元素进行判断,取出,删除的操作。
如果想要其他的操作(如添加,修改等),就需要使用其子接口,ListIterator。该接口只能通过List集合的listIterator方法获取
方法摘要 | |
| |
| hasNext |
| hasPrevious |
next | |
| nextIndex |
previous | |
| previousIndex |
| remove |
|
List子类对象:
1) ArrayList
底层的数据结构使用的是数组结构,线程不同步
特点:查询速度很快,但是增删稍慢
2) LinkedList
底层的数据结构使用的是链表数据结构
特点:增删速度很快,查询稍慢
3) Vector
底层是数组数据结构,线程同步,被ArrayList替代
LinkedList特有方法:
addFirst();
addLast();
在JDK1.6中出现以上方法替代方法:
offerFirst()
offerLast()
getFirst(); //获取元素,但不删除元素
getLast(); //如果列表为空,此操作会抛出NoSuchElementException异常
在JDK1.6中出现以上方法替代方法:
peekFirst() //获取但不移除此列表的第一个元素,如果列表为空,则返回null
peekLast()
removeFirst(); //获取元素,但是元素被删除
removeLast(); //如果列表为空,此操作会抛出NoSuchElementException异常
在JDK1.6中出现以上方法替代方法:
pollFirst(); //获取并移除此列表的第一个元素,如果列表为空,则返回null
pollLast()
public static void main(String[] args)
{
LinkedList link = new LinkedList();
link.addFirst("java01");
link.addFirst("java02");
link.addFirst("java03");
link.addFirst("java04");
sop(link); //输出结果为倒叙
}
利用List接口特点,将自定义对象作为元素存到ArrayList集合中,并去除重复元素:
import java.util.*;
class ArrayListTest2
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("lisi01",30));
al.add(new Person("lisi02",31));
al.add(new Person("lisi02",31));
al.add(new Person("lisi03",32));
al.add(new Person("lisi04",33));
al.add(new Person("lisi04",33));
al = singleElement(al);
Iterator it = al.iterator();
while (it.hasNext())
{
Person p =(Person)it.next(); //it.next()得到是Object父类的多态,转型为Person类型才能调用Person中的方法
sop(p.getName()+"::"+p.getAge());
}
}
public static ArrayList singleElement(ArrayList al)
{
ArrayList newAl = new ArrayList();
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if (!newAl.contains(obj)) //contains的原理是调用equals方法
newAl.add(obj);
}
return newAl;
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public boolean equals(Object obj) //默认方法对于对象,是判断对象的地址是否相同<span style="font-family: Arial, Helvetica, sans-serif;">所以要判断对象中内容时,需要重新定义</span>
{
if(!(obj instanceof Person)) //判断输入的对象是否是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;
}
}
List集合判断元素是否相同,依据的是元素的equals方法。remove方法也调用了equals方法判断要删除的元素是否存在于集合中
9.4Set接口
Set:元素无序(存入和取出的顺序不一定一致),元素不可以重复
Set集合的功能和Collection是一致的, Set接口取出方式只有一种,迭代器。
Set 子类对象:
1) HashSet
底层数据结构是哈希表,线程时非同步的,无序,高效
//往HashSet集合中存入自定义对象
import java.util.*;
class HashSetDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
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("a2",12));
Iterator it = hs.iterator();
while (it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge()); //相同元素不会存入
}
}
}
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}<pre name="code" class="java"><span style="white-space:pre"> </span>//HashSet存入时是先用哈希值判断是否有重复内容,<span style="font-family: Arial, Helvetica, sans-serif;">当存入对象时,各个对象的哈希值是根据地址值</span><span style="font-family: Arial, Helvetica, sans-serif;">计算的,所以要判断对象中的内容是否相同时, </span><span style="font-family: Arial, Helvetica, sans-serif;">需要重新定义给对象赋予哈希值的方法</span>
public int hashCode()
{ return name.hashCode()+age*63; } public boolean equals(Object obj) //hashCode相同时再调用equals方法判断对象{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;}}
HashSet是如何保证元素唯一性的?
是通过元素的两个方法,hashCode和equals来完成
如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals。
对于判断元素是否存在(contains()),以及删除(remove())等操作,依赖的方法是元素的hashCode和equals方法
当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
2) TreeSet
可以对Set集合中的元素进行排序,排序需要依据元素自身具备的比较性。如果元素不具备比较性,在运行时会发生ClassCastException异常。
底层数据结构是二叉树。
//往TreeSet集合中存入自定义对象
import java.util.*;
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi07",20));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi01",40));
Iterator 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 String getName()
{
return name;
}
public int getAge()
{
return age;
}<pre name="code" class="java"><span style="white-space:pre"> </span>//TreeSet会对传入的元素自然排序,<span style="font-family: Arial, Helvetica, sans-serif;">排序是调用compareTo方法来比较</span><span style="font-family: Arial, Helvetica, sans-serif;">,因此要在自定义对象中重写compareTo方法</span>
public int compareTo(Object obj) <span style="font-family: Arial, Helvetica, sans-serif;">
</span>
{
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); //当age相同时,比较字符串顺序
}
return -1;
}
}
TreeSet是如何保证元素唯一性的?
compareTo方法return 0
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparaable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性(Comparator)。在集合初始化时,就有了比较方式。
当两种排序都存在时,以比较器为主。
定义比较器:定义一个类,实现Comparator接口,覆盖compare方法。
//按照字符串长度排序
import java.util.*;
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StrLenComparator());
ts.add("abcd");
ts.add("cc");
ts.add("cba");
ts.add("aaa");
ts.add("z");
ts.add("hahaha");
Iterator it = ts.iterator();
while (it.hasNext())
{
System.out.println(it.next());
}
}
}
class StrLenComparator implements Comparator
{
public int compare(Object o1,Object o2)
{
String s1 = (String)o1;
String s2 = (String)o2;
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
if(num==0)
return s1.compareTo(s2); //长度相同比较内容
return num;
}
}
9.5 泛型
JDK1.5版本后出现的新特性,用于解决安全问题,是一个安全机制。
ArrayList<String> al = newArrayList<String>(); //泛型就是指定容器内元素的类型
Iterator<String> it = al.iterator();
好处:
1) 将运行时期出现的问题ClassCastException转移到了编译时期,方便于程序员解决问题,
让运行时期问题减少,安全
2) 避免了强制转换的麻烦
泛型格式:通过<>来定义要操作的引用数据类型
在使用java提供的对象时,什么时候写泛型?
通常在集合框架中很常见,只要见到<>就要定义泛型。其实<>就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
class LenComparator implements Comparator<String> //使用泛型,避免了强转
{
publicint compare(String s1,String s2)
{
int num = s1.length()-s2.length();
if(num==0)
returns1.compareTo(s2);
return num;
}
}
1)泛型类
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。
class GenericDemo3
{
public static void main(String[] args)
{
Utils<Worker> u = new Utils<Worker>();
u.setObject(new Worker()); //无需强转,且如果传入Student类时<span style="font-family: Arial, Helvetica, sans-serif;">会在编译时报错</span>
Worker w = u.getObject();
/*
Tool t = new Tool();
t.setObject(new Worker());
Worker w = (Worker)t.getObject();
*/
}
}
class Worker
{
}
class Student
{
}
//泛型前做法
class Tool
{
private Object obj;
public void setObject(Object obj)
{
this.obj = obj;
}
public Object getObject()
{
return obj;
}
}
//泛型后做法
class Utils<Q> //泛型类
{
private Q q;
public void setObject(Q q)
{
this.q = q;
}
public Q getObject()
{
return q;
}
}
2)泛型方法
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有方法要操作的类型就已经固定了
为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。
class GenericDemo4
{
public static void main(String[] args)
{
/*
Demo<String> d = new Demo<String>;
d.show("haha");
d.print(5); //编译时将会报错,因为对象已经指定了String类型
*/
Demo d = new Demo();
d.show("haha");
d.show(new Integer(4));
d.print("heihei"); //泛型定义在方法上就可以在一个对象中操作不同类型
}
}
class Demo
{
public <T> void show(T t)
{
System.out.println("show:"+t);
}
public <Q> void print(Q q)
{
System.out.println("print:"+q);
}
}
/*
class Demo<T>
{
public void show(T t)
{
System.out.println("show:"+t);
}
public void print(T t)
{
System.out.println("print:"+t);
}
}
*/
特殊之处:
静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上
3)泛型限定
public static void printColl(ArrayList<? extends Person> al) //接收Person类型及其子类
{
Iterator<? extends Person> it = al.iterator();
while (it.hasNext())
{
System.out.println(it.next().getName());
}
}
? 通配符,也可以理解为占位符
泛型的限定:
? extends E:可以接收E类型或者E的子类型。上限
? super E:可以接收E类型或者E的父类型。下限
9.6Map
Map<K,V>集合是一个接口,该集合存储键值对,一对一对往里存,而且要保证键的唯一性。
Map集合存储和Collection有着很大不同:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。
特点:要保证map集合中键的唯一性。
Map集合共性方法:
1)添加。put(key,value):当存储的键相同时,新的值会替换老的值,并将老值返回。如果键没有重复,返回null。
void putAll(Map);
2)删除。
void clear():清空
value remove(key) :删除指定键。
3)判断。
boolean isEmpty():
boolean containsKey(key):是否包含key
boolean containsValue(value) :是否包含value
4)取出。
int size():返回长度
value get(key) :通过指定键获取对应的值。如果返回null,可以判断该键不存在。当然有特殊情况,就是在hashmap集合中,是可以存储null键null值的。
Collection values():获取map集合中的所有的值。
5)想要获取map中的所有元素:
原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
map集合特有的两种取出方式:
1) Set<k> keySet:将map中所有的键存入到Set集合。因为Set具备迭代器,所以可以通过迭代方式取出所有的键,再根据get方法,获取每一个键对应值。
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("01","zhangsan1");
map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("04","zhangsan4");
//先获取Map集合的所有键的Set集合,keySet()
Set<String> keySet = map.keySet();
//有了Set集合,就可以获取其迭代器
Iterator<String> it = keySet.iterator();
while (it.hasNext())
{
String key = it.next();
//有了键可以通过Map集合的get方法获取其对应的值
String value = map.get(key);
System.out.println("key:"+key+",value:"+value);
}
}
}
//Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出
2) Set<Map.Entry<K,V>> entrySet:将Map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是Map.Entry
import java.util.*;
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("01","zhangsan1");
map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("04","zhangsan4");
//将Map集合中的映射关系取出,存入到Set集合中
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();
String key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
}
}
//Map.Entry :其实Entry也是一个接口,它是Map接口中的一个内部接口(静态的)
Map 子类对象:
1) Hashtable
底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的,效率低
2) HashMap
底层是哈希表数据结构,并允许使用null值和null键,该集合是不同步的,效率高
3) TreeMap
底层是二叉树数据结构,线程不同步。可以用于给map集合中的键进行排序
Map集合和Set集合很像,其实Set底层就是使用了Map集合
当数据之间存在着映射关系时,就要想到map集合
9.7Utilities
1) Collections
Collections是专门用于对集合进行操作的工具类,其内部的方法都是静态的。
sort:对指定列表进行排序
Collections.sort(List<T> list);
Collections.sort(List<T> list,Comparator<? super T> comp);
max:返回给定 collection 的最大元素
Collections.max(Collection<? extends T> coll)
Collections.max(Collection<?extends T> coll,Comparator<? super T> comp)
binarySearch:使用二分搜索法搜索指定列表,获得指定对象
Collections.binarySearch(List<? extendsComparable<? super T>> list, T key) List中元素自身有比较性时使用
Collections.binarySearch(List<? extendsT> list, T key, Comparator<? superT> c) List中元素自身无比较性时调用比较器
fill:使用指定元素替换指定列表中的所有元素
Collections.fill(List<? super T>list,T obj)
replaceAll:使用另一个值替换列表中出现的所有某一指定值
Collections.replaceAll(List<T> list,ToldVal,T newVal)
reverse:反转指定列表中元素的顺序
Collections.reverse(List<?> list)
reverseOrder:返回一个比较器,它强行逆转指定比较器的顺序
Collections.reverseOrder() 逆转自然顺序
Collections.reverseOrder(Comparator<T>comp) 逆转comp比较器的顺序
shuffle:使用默认随机源对指定队列进行置换(随机排序)
Collections.shuffle(List<?> list)
将非同步集合转成同步集合的方法:Collections中的 XXX synchronizedXXX(XXX);
List synchronizedList(list);
Map synchronizedMap(map);
原理:定义一个类,将集合所有的方法加同一把锁后返回。
Collection 和 Collections的区别:
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
2) Arrays
用于操作数组的工具类,里面都是静态方法
asList:将数组变成list集合
Arrays.asList(arr)
把数组变成集合可以使用集合的思想和方法来操作数组中的元素,比如用contains方法判断元素是否存在。将数组变成集合,不可以使用集合的增删等会改变数组长度的功能方法,因为数组的长度是固定的。(否则会报不支持操作异常UnsupportedOperationException)
如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
3)集合转成数组
Collection.toArray(T[ ] arr):返回包含此collection中所有元素的数组(T类型的数组)
import java.util.*;
class CollectionToArray
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
String[] arr = al.toArray(new String[5]);
System.out.println(Arrays.toString(arr)); //输出:[abc1, abc2, abc3, null, null]
String[] arr = al.toArray(new String[al.size()]); //最优
}
}
指定类型的数组到底要定义多长?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建数组,而是使用传递进来的数组。
所以创建一个刚刚好的数组最优。
为什么要将集合变成数组?
为了限定对元素的操作,不需要进行增删了
4)增强for循环
格式:
for(数据类型 变量名:被遍历的集合(Collection)或者数组){}
对集合进行遍历,只能获取元素,但是不能对集合进行操作。
迭代器除了遍历,还可以进行remove集合中元素的动作。如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
传统for和高级for有什么区别?
高级for有一个局限性,必须有被遍历的目标。这个目标,可以是Collection集合或者数组,如果遍历Collection集合,在遍历过程中还需要对元素进行操作,比如删除,需要使用迭代器。
建议在遍历数组的时候,还是希望使用传统for,因为传统for可以定义角标。
高级for循环可以遍历map集合吗?不可以。但是可以将map转成set后再使用foreach语句。
import java.util.*;
class ForEachDemo
{
public static void main(String[] args)
{
ArrayList<String> al = new ArrayList<String>();
al.add("abc1");
al.add("abc2");
al.add("abc3");
for (String s : al)
{
System.out.println(s);
}
HashMap<Integer,String> hm = new HashMap<Integer,String>();
hm.put(1,"a");
hm.put(2,"b");
hm.put(3,"c");
for (Integer i : hm.keySet() ) //利用高级for替代Iterator
{
System.out.println(i+"::"+hm.get(i));
}
for(Map.Entry<Integer,String> me : hm.entrySet())
{
System.out.println(me.getKey()+"---"+me.getValue());
}
}
}
5)可变参数
方法的可变参数在使用时,可变参数一定要定义在参数列表的最后面。
class ParamMethodDemo
{
public static void main(String[] args)
{
show("haha",2,3,4,5);
}
public static void show(String str,int...arr)
{
System.out.println(arr.length);
}
}
10.其他对象
10.1System类
System类中的方法和属性都是静态的
out:标准输出,默认是控制台
in:标准输入,默认键盘
获取系统属性信息:System.getProperties() 返回的是Properties类(Hashtable的子类)
设置自定义信息:System.setProperty(K,V)
获取指定属性信息:System.getProperty(K) 返回的是对应键的值(String类)
import java.util.*;
class SystemDemo
{
public static void main(String[] args)
{
Properties prop = System.getProperties();
//在系统中自定义一些特有信息
System.setProperty("mykey","myvalue");
/*
因为Properties是Hashtable的子类,也就是Map集合的一个子类对象
那么可以通过map的方法取出该集合中的元素
该集合中存储的都是字符串,没有泛型定义
*/
for ( Object obj : prop.keySet())
{
String value = (String)prop.get(obj); //没有指定泛型要强转
System.out.println(obj+"---"+value);
}
//获取指定属性信息
String value = System.getProperty("os.name");
/*在jvm启动时,动态加载一些属性信息
在cmd中:java -Dxxx -yyyy SystemDemo
则在SystemDemo.java中
System.getProperty("xxx")得到的结果为yyyy
*/
}
}
10.2 Runtime类
该类中并没有提供构造函数,说明不可以new对象。该类中提供了静态方法来获取本类对象,返回值类型是本类类型:static Runtime getRuntime() 。 此类为单例设计模式。
打开应用程序:exec(String command)
class RuntimeDemo
{
public static void main(String[] args) throws Exception
{
Runtime r = Runtime.getRuntime();
Process p = r.exec("c:\\Windows\\notepad.exe SystemDemo.java");
//系统根目录下的应用程序可以省略目录。可以用notepad程序打开与程序相关联的SystemDemo.java文件
Thread.sleep(4000);
//p.destroy(); //杀掉子进程
}
}
10.3Date类
import java.util.*;
import java.text.*;
class DateDemo
{
public static void main(String[] args)
{
Date d = new Date();
System.out.println(d);
//将模式封装到SimpleDateFormat对象中
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E HH:mm:ss");
//调用format方法让模式格式化指定Date对象
String time = sdf.format(d);
System.out.println(time);
}
}
10.3Calendar类
import java.util.*;
import java.text.*;
class CalendarDemo
{
public static void main(String[] args)
{
Calendar c = Calendar.getInstance();
String[] mons = {"一月","二月","三月","四月",
"五月","六月","七月","八月",
"九月","十月","十一月","十二月"};
String[] weeks = {"","星期日","星期一","星期二","星期三",
"星期四","星期五","星期六"};
int index = c.get(Calendar.MONTH);
int index1 = c.get(Calendar.DAY_OF_WEEK);
sop(c.get(Calendar.YEAR)+"年");
//sop((c.get(Calendar.MONTH)+1)+"月"); //Calender中的Month是从0开始的
sop(mons[index]);
sop(c.get(Calendar.DAY_OF_MONTH)+"日");
//sop("星期"+c.get(Calendar.DAY_OF_WEEK));//Calender中是将星期日作为一个星期的第一天
sop(weeks[index1]);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
set(int year,int month,int date):将日历设置为指定日期
add(int field,int amount):为给定的日历添加或减去指定的时间量
10.4Math类
Math.ceil(double d):返回大于指定数据的最小整数。
Math.floor(double d):返回小于指定数据的最大整数。
Math.round(double d):四舍五入。返回值类型为long。
Math.pow(double a,double b):返回a的b次方。
Math.random():返回大于等于0.0且小于1.0的double随机数。