最近在看java编程思想,做一个小总结。有写错的地方还请改正。谢谢
对于数组,由于其不可变长,且只能存储基本类型数据,所以不是很方便。于是就出现了可以存储对象,并且长度可变的容器。Collection(List,Set,Vector),Map。
*************泛型安全的容器********************************
在javaSE5之前允许向容器中加入不正确的类型:
ArrayList apples=new ArrayList();//未使用泛型,所以默认保存object类型,于是apple对象和orange对象都被加入其中。
apples.add(new Apple());
apples.add(new Orange());
for(int i=0;i<apples.size();i++){
(Apple)apples.get(i);//runtime时此处会报错。
}
于是之后出现了预定义的泛型,此时,定义:
ArrayList<Apple> apples=new ArrayList<Apple>();
apples.add(new Apple1());
apples.add(new Apple2());
apples.add(new Apple3());
apples.add(new Orange());//compile时会报错
for(Apple a:apples){
System.out.println(c);
}
可以发现,使用泛型后,get操作的向下转型也不是必须的了。同时,Apple的子类new出的对象,是可以添加到apples这个容器中的。由于程序的输出是从Object默认的toString()方法产生的,而Apple及其子类都没有复写Object中的toString函数,所以会打印出该对象的散列码的十六进制表示。(此散列码由hashCode方法产生)
********************基本概念*******************************
List<Apple> apples=new ArrayList<Apple>();
以上是一个通常定义list的方式。这是向上转成一个通用接口(创建更通用的代码,使得代码可以应用于更多的类型)。但是这样对于ArrayList特有的方法,apples是无法调用的。
Collection<Integer> c=new ArrayList<Integer>();//用integer对象填充一个collection
for(int i=0;i<10;i++){
c.add(i);
}
for(Integer j:c){
System.out.println(j+",");//由于在Integer类中复写了toString()方法:toString(),
返回一个表示该 Integer
值的 String
对象。
}//所有的collection都可以使用foreach遍历
*********************添加一组元素*******************************************
此处需要了解关于Collection和Collections的区别:
Collection是一个接口,在java中有许多具体实现类,如list,set这些,可以用上面的方法进行实例化。
Collections:它包含在 collection 上操作的多态算法,即“包装器”,是对于给定的collection或list参数等进行操作。本身不可实例化。
##########################################
Collection<Integer> c=new ArrayList<Integer>();
Integer[] array={4,5,6};
c.addAll(Arrays.asList(1,2,3));
c.addAll(Arrays.asList(array));//collection的addall方法中传的参数是一个Collection的对象,此处调用Arrays中的asList方法将一个数组转换成了list对象传入
Collections.addAll(c, 7,8,9);//Collections的addAll方法中指定向c加入7,8,9三个元素。可见这个很灵活。
for (Integer integer : c) {
System.out.println(integer);
}
ps:List<Integer> list=Arrays.asList(2,3,4);//直接使用Arrays.asList的输出,底层表示仍然是数组,不可执行add与delete操作
Collection<Integer> c=new ArrayList<Integer>(Arrays.asList(2,3,4));//写成这样可以做add与delete操作
Arrays.asList方法对于所产生的list类型做最理想的假设,并没有注意会被赋予什么类型
##########################################
class Snow{}
class Snow1 extends Snow{}
class Snow2 extends Snow{}
class Snow11 extends Snow1{}
class Snow12 extends Snow1{}
List<Snow> list1=Arrays.asList(new Snow1(),new Snow2(),new Snow11());
List<Snow> list2=Arrays.asList(new Snow11(),new Snow12());//由于只存入了snow11和snow12创建的对象,所以这个list会被创建为List<Snow1>,而不是List<Snow>。也就是上面提到的做最理想的假设。
List<Snow> list3=new ArrayList<>();
Collections.addAll(list3, new Snow11(),new Snow12());//而Collections不会出现上面的问题,因为从第一个参数了解到了目标类型是什么。
List<Snow> list4=Arrays.<Snow>asList(new Snow11(),new Snow12());//所以在使用Arrays.asList时要进行显示类型参数说明。%%%%%%%%%%%%%可是我跑代码的时候有点问题。。。。
****************************容器的打印*****************************************
直接用System.out.println();
ArrayList和LinkedList都是按照插入的顺序打印出来。区别仅在于LinkedList的操作更多一些。
HashSet按照一种复杂的方式存储插入的元素,打印出数据看似是很奇怪的顺序,只关心某个元素是否在HashSet内,而不关心出现在set中的顺序。是最快取元素的方式。
TreeSet按照升序的方式保存对象。
LinkedHashSet按照插入的顺序保存对象。
HashMap与Hashset一样,按照复杂的方式存储数据
TreeMap按照键的升序存储数据
LinkedHashMap按照插入的方式存储数据。
###################################
List<String> list=new ArrayList<String>();
list.add("aaa");
list.add("fff");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("ggg");
List<String> subList=list.subList(0, 3);
System.out.println(subList);
Collections.sort(subList);
System.out.println(list);
System.out.println(subList);
output:[aaa, fff, bbb]
[aaa, bbb, fff, ccc, ddd, eee, ggg]
[aaa, bbb, fff]//subList来自于初始表list,发现对subList排序,其初始列表也排序了。
########################
*******************************迭代器*****************************
Iterator<String> iterator=list.iterator();
while(iterator.hasNext()){
String string=iterator.next();//转成string后再输出,而不是直接把iterator.next后直接输出iterator,
System.out.println(string);
}
#######################
List<String> list=new ArrayList<String>();
list.add("aaa");
list.add("fff");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("ggg");
Iterator<String> iterator=list.iterator();
for(int i=0;i<3;i++){
iterator.next();
iterator.remove();//使用remove将新近放到iterator中的元素删除
}
output:[ccc, ddd, eee, ggg] 发现list中的前三个元素被删除
#################################
ListIterator:只能用于对List类的访问,可以双向移动。可以获取迭代器在列表中指向的当前元素的前一个和后一个元素的索引。可以用set方法替换访问过的最后一个元素。可以直接对于list调用listIterator方法产生指向list开始处的一个迭代器,也可以通过调用listIterator(n)产生指向索引值为n处的迭代器。
List<String> list=new ArrayList<String>();
list.add("aaa");
list.add("fff");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("ggg");
ListIterator<String> listIterator=list.listIterator();
List<String> list2=new ArrayList<String>();
while(listIterator.hasNext()){
listIterator.next();
}
while(listIterator.hasPrevious()){
list2.add(listIterator.previous());
}
System.out.println(list2);//实现倒序输出一个list。
*******************************LinkedList*********************************
getFirst(),element(),peek():返回但不移除头元素。差异:peek在list为空时返回null,另外两个在list为空时抛出异常。
remove(),removeFirst(),poll():返回并移除头元素。差异:poll在list为空时凡湖inull,另两个抛出异常。
add(),addFirst(),addLast():在头或尾部插入元素
add(int index, E element)
在此列表中指定的位置插入指定的元素
addAll(int index, Collection<? extends E> c)
将指定
collection 中的所有元素从指定位置开始插入此列表。
*******************************stack********************
可以由linkedlist实现。
push:添加元素到栈顶
pop:移除栈顶对象,并且返回此对象
peek:返回栈顶对象,不移除
empty:判断是否为空
****************************Set**********************
set不保存重复元素,主要作用在于查找。尤其HashSet查找速度快,功能强大,常用于测试某个对象是否在某个set中。set其实就是collection,不过是不允许存在重复元素。所以在addAll以及add函数中,都有首先判断是否已经存在当前要加入的对象,这一操作。
treeSet:可以自行设定存储数据的方式
TreeSet<String> treeSet=new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o1.compareTo(o2);//添加负号更改排序规则
}
});
treeSet.add("e");
treeSet.add("b");
treeSet.add("a");
System.out.println(treeSet);
TreeSet<String> treeSet2=new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);//该常量表示按照字母顺序排序
Collections.addAll(treeSet2, "if you do love her you can tell her".split(" "));
System.out.println(treeSet2);
*******************************Map**********************************
键值对,键唯一。新put的键值对如果之前键已经存在,那么会更新成后加入的键值对。
Map<Integer, Integer> map=new HashMap<Integer,Integer>();
Random random =new Random(30);
for(int i=0;i<100;i++){
int r=random.nextInt(20);
if(map.containsKey(r)){
int freq=map.get(r);
map.put(r, freq+1);//如果当前生成的随机数已经存在于map中,那么把freq加一作为新的值放到map中
}else{
map.put(r, 1);
}
}//统计每个生成的随机数出现过几次
map可以很方便的扩展到多维,之前有做过在list的元素为map,其实map里面的value也可以是list:
Map<Integer, List<String>> map=new HashMap<Integer,List<String>>();
List<String> list1=new LinkedList<String>();
Collections.addAll(list1, "dog","cat");
List<String> list2=new LinkedList<String>();
Collections.addAll(list2, "dog","cat","elephant");
map.put(1, list1);
map.put(2, list2);
System.out.println(map);
output:{1=[dog, cat], 2=[dog, cat, elephant]}
改成如下打印方式:for(Integer t:map.keySet()){//keyset函数返回map中以key为元素的set(就是一个collection),再通过遍历这个keyset,取出value
System.out.print(t+":");
for(String s:map.get(t)){
System.out.print(s+",");
}
System.out.println();
}
output: 1:dog,cat,
2:dog,cat,elephant,
***************************Queue**************************
先进先出的容器。由LinkedList实现。从容器一端放入事物,另一端取出。事物放入容器的顺序与取出的顺序是相同的。
peek(),element():返回队列头元素,不移除。peek在为空时返回null,element抛异常
poll(),remove():返回队列头元素,移除。差异同上。
offer()与add():往队列添加元素。在queue有容量限制时,offer方法一般有较高优先级。add可能无法插入元素,仅仅是抛出异常。
********************************************priorityQueue*****************************
Comparator<Integer> comparator=new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return -o1.compareTo(o2);
}
};
PriorityQueue<Integer> priorityQueue=new PriorityQueue<Integer>(3, comparator);
按照comparator定义的降序或升序输出,
*************************************foreach与迭代器**************************
java se5中引入Iterable接口,该接口包含一个能够产生Iterator的iterator方法。只要创建实现了Iterable的类,都可以用于foreach中。
public class HoldingObject implements Iterable<String> {
protected String[] words="i do believe you".split(" ");
@Override
public Iterator<String> iterator() {
// TODO Auto-generated method stub
return new Iterator<String>() {
private int index=0;
@Override
public boolean hasNext() {
return index<words.length;
}
@Override
public String next() {
return words[index++];
}
@Override
public void remove() {
//no implemented
}
};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for(String s:new HoldingObject()){
System.out.println(s);
}
}
####
foreach语句可以用于数组和任意iterable,但并不是说数组是iterable的。所以尝试把数组当做一个iterable参数传递会失败。任何从数组到iterable的自动转换都不存在,只有手动使用Array.asList(数组)才可以实现由数组到iterable转换。
******************************************Map的一些介绍************************
entrySet方法将map中的键值对作为元素放到set中()。
Map<String,String> map=new HashMap<String, String>();
map.put("1", "girl");
map.put("2", "boy");
Set<Map.Entry<String, String>> set=map.entrySet();
System.out.println(set);
System.out.println(map);
output:[2=boy, 1=girl]
{2=boy, 1=girl}
在获取Map.Entry后还可以这样遍历:
for(Map.Entry entry:set){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
output:2
boy
1
girl
****************************************foreach与迭代器*****************************************
如果希望选择以向前或者向后的方式迭代一个单词列表,怎么办?如果现在有这样一个类实现了iterable这个借口,那么是可以用foreach迭代,但是不能以多种方式迭代。采取适配器惯用法。
也就是说当有一个借口并且需要另一个接口时,编写适配器可以解决这个问题。
public class ReversibleArrayList<T> extends ArrayList<T>{//继承arraylist,内含literator方法,但是是正向的。不可采用继承
public ReversibleArrayList(Collection<T> c){
super(c);
}
public Iterable<T> reversed(){//添加一个能够返回iterable对象的方法。
return new Iterable<T>(){
@Override
public Iterator<T> iterator() {
// TODO Auto-generated method stub
return new Iterator<T>(){
int current=size()-1;
@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return current>-1;
}
@Override
public T next() {
// TODO Auto-generated method stub
return get(current--);
}
};
}
};
}
}
主函数中调用:
public static void main(String[] args){
ReversibleArrayList<String> ral=new ReversibleArrayList<String>(Arrays.asList("to be or not to be".split(" ")));
for(String s:ral){
System.out.print(s+" ");
}
System.out.println();
for(String s:ral.reversed()){
System.out.print(s+" ");
}
}
to be or not to be
be to not or be to
通过这种方式可以添加多种适配器。
*****************************************************************************