还有一天半就要换个地方了,所以这短暂的时间里需要进行一些扫尾工作,上次的Java还有集合和反射没有更新完,还有深入理解Java虚拟机有几章还没来得及整理,所以时间上比较急,开始介绍一下Java集合
Java集合定义
集合之所以会诞生,是因为Java数组虽然可以存放基本数据类型也可以存放引用数据类型,但是数组的长度是固定的,很不方便,集合的长度是不固定的,所以就引入了集合的概念。
集合和数组很像,但是有明显区别,集合只能存储引用数据类型,不能存放基本数据类型,且集合的长度没有固定。
集合又称之为类集或容器
集合类主要由两个接口派生:Collection和Map,还有个集合工具类Collections
Collection接口
Java.util.Collection中Collection接口的定义
public interface Collection<E> extends Iterable<E>
可以发现Collection采用的是泛型技术,故而在操作时必须指定具体的操作类型,利于集合的安全性,Collection时List和Set接口的父接口。
虽然Collection是集合类的基本接口,但一般不会直接使用Collection接口进行操作,而是使用其子接口。Collection接口的主要子接口有如下几个。
- List< E> :集合 中的元素按照索引值来排序,允许存放重复的元素。List集合和数组相似。
- Queue< E>:队列接口,通常以先进先出的方式排序各个元素。
- Set< E>:集合中的元素不按特定方式排序,不能存在重复对象,但其有些实现类能对集合中的元素按照特定的方式排序。
- SortedSet< E>:可以对集合中的元素进行排序。
List接口
一个有序集合,其元素以线性方式存储,集合中允许存放重复元素,包括null,旗下有Array List和ListedList。
ArrayList类
ArrayList类实现List接口,可以直接通过ArrayList为List接口实例化,允许对集合中的元素进行快速访问,但向ArrayList集合中插入或删除速度较慢。
示例:
package zhao_test;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String []args){
Collection<String> collection =new ArrayList<String>();
List<String> list=new ArrayList<String>();
collection.add("1");
collection.add("2");
collection.add("3");
list.add("A");
list.add("C");
list.add(1,"B");
list.addAll(0,collection);
System.out.println("list集合:"+list);
List<String> subList=list.subList(1,5);
System.out.println("sublist(1,5)集合:"+subList);
System.out.println("获得list的第3个元素值:"+list.get(2));
list.set(2,"Set");
System.out.println("设置list的第3个元素值:"+list.get(2));
String arr[]=list.toArray(new String[]{});
System.out.print("List转换为String数组:\n");
for(String str:arr)
System.out.print(str+" ");
System.out.print("\nlist集合是否为空:"+list.isEmpty());
list.clear();
System.out.print("\nlist集合是否为空:"+list.isEmpty());
}
}
ArrayList类提供将集合转换为数组的toArray()方法,并没有提供将数组转为集合的方法,但Arrays类提供了asList()方法可以将数组转换为List集合。
ListedList类
链表类,拥有链表的优点,方便插入和删除,但不易查询元素。
List接口中没有定义addFirst()和addLast()方法,所以不能使用List<String> link=new LinkedList<String>();
用法示例:
package zhao_test;
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String []args){
LinkedList<String> link=new LinkedList<String>();
link.add("1");
link.add("2");
link.add("3");
System.out.println("添加前:"+link);
link.addFirst("F");
link.addLast("L");
System.out.println("添加后:"+link);
}
}
LinkedList获取表头的方法:
package zhao_test;
import sun.awt.image.ImageWatched;
import java.util.LinkedList;
public class LinkedListDemo2 {
public static void main(String[]args ){
LinkedList<String> link=new LinkedList<String>();
link.add("1");
link.add("2");
link.add("3");
link.addFirst("F");
link.addLast("L");
LinkedList<String> newList=new LinkedList<String>(link);
System.out.println("List:"+link);
System.out.println("get()方法获取表头:"+link.getFirst());
System.out.println("list: "+link);
System.out.println("element()方法获取表头:"+link.element());
System.out.println("list: "+link);
System.out.println("peek()方法获取表头:"+link.peek());
System.out.println("list: "+link);
System.out.println("poll()方法获取表头:"+link.poll());
System.out.println("list: "+link);
System.out.println("pop()方法获取表头:"+link.pop());
System.out.println("list: "+link);
System.out.println("链表的先进先出:");
for(int i=0;i<newList.size();i++)
System.out.print(newList.poll()+" ");
}
}
由上述结果可见,poll()和pop()方法获取表头是将表头弹出,最后的红箭头处值得注意,这也体现了集合的动态性。
Set 接口
Set是一个不包含重复元素的Collection,Set允许null,但只允许一个Set一个null,旗下有HashSet和TreeSet类.
散列集:HashSet类
使用哈希算法来存取集合中的元素,当向HashSet集合中添加元素时,就会调用该元素的hashCode()方法,获取其中的哈希值,然后根据这个哈希值计算出该元素的存放位置。同时需要重写equals()和hashCode()方法。
HashSet集合具有以下特点:
不能保证元素的排列顺序
集合中最多允许存放一个null元素
HashSet集合不是线程同步的。
如果没有重写equals()方法和hashCode()方法,示例:
package zhao_test;
import java.util.Set;
import java.util.HashSet;
class Person{
private String name;
private int age;
public Person(){
}
public Person(String name,int age){
this.name=name;
this.age=age;
}
public String toString(){
return ("name:"+name+",age:"+age+"\n");
}
}
public class HashSetDemo1 {
public static void main(String []args){
Set<Person> set=new HashSet<Person>();
set.add(new Person("你好",10));
set.add(new Person("你好",10));
System.out.print(set);
}
}
运行结果如图所示,竟然能存在着相同的东西,不可思议,这与前面所讲的Set集合不允许存在两个相同的元素相违背,之所以会出现这种情况,是因为这2个new person(”你好“,10)不在同一个内存地址对象中,即Person类没有重写过equals和hahsCode方法,所以引用类型比较的是地址而不是对象本身。
重写了equals和hashCode方法的HashSet集合
package zhao_test;
import java.util.Set;
import java.util.HashSet;
class Person2{
private String name;
private int age;
public Person2(String name,int age){
this.name=name;
this.age=age;
}
public boolean equals(Object o){
if(this==o){
return true;
}
if (o==null)
return false;
if(!(o instanceof Person2)){
return false;
}
Person2 per=(Person2)o;
if(this.name.equals(per.name)&&this.age==per.age){
return true;
}else return false;
}
public int hashCode(){
final int prime=13;
int result=13;
result =prime*result+((name==null)?0:name.hashCode());
result=prime*result+age;
return result;
}
public String toString(){
return ("name:"+name+",age:"+age+"\n");
}
}
public class HashSetDemo2 {
public static void main(String []args){
Set<Person2> set=new HashSet<Person2>();
set.add(new Person2("你好",10));
set.add(new Person2("你好",10));
System.out.print(set);
}
}
从结果中可以看到,最终的Set中就只有这么一个了。
树集:TreeSet类
TreeSet类实现了java.util包中的Set接口和SortedSet接口。TreeSet集合中的元素在默认情况下是升序,当然如果想自定义自己的排序方式可以使用TreeSet类的构造方法TreeSet(Comparator comparator)。
验证下TreeSet集合的默认排序
package zhao_test;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetDemo1 {
public static void main(String []args){
Set<Integer> test=new TreeSet<Integer>();
test.add(1);
test.add(1);
test.add(2);
test.add(5);
test.add(4);
test.add(3);
System.out.print(test);
}
}
从结果中可以看到,TreeSet默认为升序,且去重。
自定义的类排序
若想自定义的类创建的多个对象可以添加到TreeSet集合中,就需要让该自定义类实现Comparable接口,一个类实现Comparable接口必须实现该接口中的int
compareTo()方法;若没有实现Compareable接口的类,只能向TreeSet集合添加一个对象,若添加多个对象,则会产生ClassCastException异常
实现compareTo接口示例:
package zhao_test;
import java.util.Set;
import java.util.TreeSet;
class Person3 implements Comparable<Person3>{
private String name;
private int age;
public Person3(){
}
public Person3(String name,int age){
this.name=name;
this.age=age;
}
public int compareTo(Person3 per) {
if (this.age > per.age)
return 1;
else if(this.age<per.age)
return -1;
else return this.name.compareTo(per.name);
}
public String toString(){
return ("name:"+name+",age:"+age+"\n");
}
}
public class TreeSetDemo3 {
public static void main(String []args){
Set<Person3> test=new TreeSet<Person3>();
test.add(new Person3("我好",10));
test.add(new Person3("你好",20));
test.add(new Person3("我好",15));
System.out.print(test);
}
}
迭代输出:Iterator接口
示例:
package zhao_test;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
public class IteratorDemo1 {
public static void main(String []args){
LinkedList<String> link=new LinkedList<String>();
link.add("1");
link.add("2");
link.add("3");
link.add("a");
link.add("b");
Iterator<String> it=link.iterator();
while(it.hasNext())
System.out.print(it.next()+" ");
}
}
Map接口
Map集合中保存键值对,key和value都可以是任何引用数据类型。Map集合中的key不允许重复,每一个key只能映射一个value。key还决定着存储对象在映射中的存储位置,但这不是由key本身决定的,而是由散列技术进行处理的。
Map接口中有多个实现类,较为常用的为HashMap和TreeMap
HashMap
HashMap是基于哈希表的Map接口的实现,允许使用null键和null值,但必须保证键是唯一的。HahsMap是非同步的,也不保证映射顺序。
- 获取Map集合中全部的key和value(Map是使用的二元偶对象,而Iterator一次只输出一个值,故需要进行处理)
package zhao_test;
import java.util.*;
public class HashMapDemo1 {
public static void main(String []args){
Map<Integer,String> map=new HashMap<Integer, String>();
map.put(1,"清华大学");
map.put(2,"北京大学");
map.put(3,"复旦大学");
Set<Integer> set=map.keySet();
Iterator<Integer> itKey=set.iterator();
System.out.println("Map集合中全部的key: ");
while (itKey.hasNext()){
System.out.print(itKey.next()+" ");
}
System.out.println();
Collection<String> c=map.values();
Iterator<String> itValues=c.iterator();
System.out.println("map中的全部values");
while(itValues.hasNext())
System.out.print(itValues.next()+" ");
}
}
Map.Entry接口
public static interface Map.Entry<K,V>
Map.Entry接口是静态的,所以可以直接使用
使用foreach输出Map集合
package zhao_test;
import java.util.Map;
import java.util.HashMap;
public class HashMapDemo2 {
public static void main(String[]args){
Map<Integer,String> map=new HashMap<Integer, String>();
map.put(1,"清华大学");
map.put(2,"北京大学");
map.put(3,"复旦大学");
System.out.println("key--Value");
for(Map.Entry<Integer,String> mapEntry:map.entrySet())
System.out.println(mapEntry.getKey()+"-----"+mapEntry.getValue());
}
}
有序树映射类:Tree Map类
Tree Map集合主要是对所有的key进行排序,从而保证所有的key-value映射关系处于有序状态,其默认的排序方式为升序方式。
集合工具类:Collections
- Collection和Collections的区别
Collection是Java.util包中的接口,是集合类的基本接口,主要子接口有List和Set。
Collections是Java.util包中的类,是针对集合的一个实用工具类,它包含各种集合的搜索、排序和线程安全等一系列的静态方法。
示例:
package zhao_test;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
public class CollectionDemo1 {
public static void main(String []args){
List<String> list=new ArrayList<String>();
list.add("A");
list.add("B");
Collections.addAll(list,"1","2","3");
Iterator<String> it=list.iterator();
System.out.println("输出集合中的元素");
while (it.hasNext())
System.out.print(it.next()+" ");
System.out.print("\n排序后:\n");
Collections.sort(list);
for(String s:list)
System.out.print(s+" ");
Collections.reverse(list);
System.out.println("\n反序:");
Iterator<String> it1=list.iterator();
while(it1.hasNext())
System.out.print(it1.next()+" ");
}
}
关于ArrayList与Vector的区别
Vector是线程安全的,也就是说它的方法之间是线程同步的,而ArrayList是线程不安全的,方法也是线程不同步的,
关于HashMap和Hashtable的区别
Hash Map和Hashtable都是Map接口的实现类,而HashMap是Hashtable的轻量级实现(非线程安全的实现),即Hashtable是线程安全的,也就是说同步的,性能相对较低,而HashMap是线程不安全的,不是同步的,性能相对较高。
值: Hashtable不允许存在null值和null值,而HashMap允许存在一个null键和多个null值。
小结
最近真是乱,得赶快调整下心态,抓紧时间,毕竟大学只有三年