学习日志_集合框架
Java语言_集合框架
{
Collection
|——List
|——ArrayList
|——Set
|——HashSet
|——TreeSet
集合框架就是容器,因为它们的存储方式(数据结构)不同,有所差异
集合是一种可以容纳多个对象的对象。与数组不同,集合对象的容量会根据需要自动扩展,
以容纳添加到其中的所有对象,因此,编程时并不需要关心将来添加到其中的对象的个数
Collection的共性方法
①添加元素
c.add(对象);//add方法的参数类型是Object,以便于接收任意类型的对象;集合中存储的
都是对象的引用(地址)
②获取长度,个数
c.size();
③打印集合
System.out.println(c);//打印的是对象
④删除元素
c.remove(对象);
c.clear();清空集合
⑤判断元素
c.contains(obj);//是否存在
c.isEmpty();//是否为空,为空返回true
⑥取交集
c.retainAll(c2)//c中只会保留和c2相同的元素
迭代器
接口 Iterator :对 collection 进行迭代的迭代器
Iterator it = al.iterator();//获取迭代器,用于取出集合元素
Iteratro 中的方法
it.hasNext();//如果有元素,返回true
it.next()//返回迭代的下一个元素
什么是迭代器
其实就是集合的元素取出方式,把取出方式定义在集合的内部,这样取出方式就可以直接访问
集合内部的元素,那么,取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以
取出的动作细节也不一样,但是都有共性内容:判断和取出。那么,也可以将这些共性内容进行
抽取。这些抽取出来的规则就是Iterator。通过一个对外提供的方法iterator()。就可以获取
集合的取出对象。
例:
/*集合框架__迭代器*/
import java.util.*;//导入java工具包
class IteratorDemo
{
public static void main(String[] args)
{
ArrayList al = new ArrayList();//创建一个集合容器
al.add("java01");//添加元素
al.add("java02");
al.add("java03");
sop("size="+al.size()); //获取长度
Iterator it = al.iterator();//获取迭代器
while(it.hasNext())//如果仍有元素可以迭代,则返回 true。
{
sop(it.next());//返回迭代的下一个元素。
}
/*
迭代器也可以这样写,因为这样比较节省资源
for(Iterator it = al.iterator();it.hasNext();)
{
sop(it.next());
}
*/
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
<1>List集合
凡是可以操作角标的方法都是该体系特有方法
List集合共性方法
①添加元素
add(index,element)
addAll(index,collection);
②删除元素
remove(index);
③修改元素
set(index,element);
④查找元素
get(index);
subList(fromIndex,toIndex);
listIterator();
indexOf();
List集合特有的迭代器
listIterator是Iterator的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生并发修改异常
所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能
对元素进行判断和取出删除的操作
如果想要其它的操作如:添加修改等,就需要使用其子接口,listIterator
*该接口只能通过List集合的listIterator方法获取,只有listIterator具备增删改查,
因为List集合有角标
例:
/*集合框架__List集合共性方法*/
import java.util.*;//导入集合工具包
class ListDemo
{
public static void main(String[] args)
{
ArrayList li = new ArrayList();//创建集合
li.add("java01");//添加元素
li.add("java02");
li.add("java03");
sop("li="+li);
li.add(2,"java04");//添加元素
sop("li="+li);
li.remove(2);//删除元素 ArrayList中特有方法remove(index);
sop("li="+li);
li.set(2,"java06");//用指定的元素替代此列表中指定位置上的元素。
sop("li="+li);
sop("sub="+li.subList(2,3));//返回列表中指定的fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
sop(li);
ListIterator ll = li.listIterator();//list集合中特有迭代器listIterator
while(ll.hasNext())
{
Object obj = ll.next();
if(obj.equals("java06"))
ll.set("java03");//listIterator中的替换操作
}
sop("li = "+li);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
总结:
List:元素有序,可以重复,因为有索引
ArrayList:底层的数据结构使用的是数组结构,特点:查询速度快,但是增删速度慢;线程不同步
<2>Set集合
元素无序,元素不可以重复(存入和取出的顺序不一定一致)
HashSet:元素无序,底层数据结构(哈希表)非同步
HashSet是如何保证元素的唯一性?
是通过元素的两个方法:hashCode和equals来完成的,如果元素的HashCode值相同,才会判断equals
是否为true,如果元素的hashCode不同,不会调用equals方法
注意:对于判断元素是否存在,以及删除操作,依赖的方法是元素的hashCode和equals方法
例:
/*Set__HashSet*/
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 int hashCode()//重写hashCode方法
{
return name.hashCode()+age*22;
}
public boolean equals(Object obj)//重写equals方法,这里用Object接收
{
if(!(obj instanceof Person))
throw new ClassCastException("不是Person对象");
Person p = (Person) obj;//这里要进行强制转换
return this.name.equals(p.name) && this.age == p.age;
}
}
class HashSetTest
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add(new Person("zhangsan",11));
hs.add(new Person("lisi",12));
hs.add(new Person("lisi",12));
hs.add(new Person("wangwu",13));
hs.add(new Person("wangwu",13));
hs.add(new Person("zhaoliu",13));
Iterator it = hs.iterator();//创建迭代器
while(it.hasNext())
{
Person p = (Person) it.next();
sop("name = "+p.getName()+"...age = "+p.getAge());//输出内容
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
TreeSet:可以对Set集合中的元素进行排序
排序时,当主要条件相同时,一定要判断一下次要条件,对象类强制实现Comparatable接口,让该类对象
具有比较性,并重写compareTo方法。
底层数据结构是二叉树,和哈希值无关,与CompareTo有关
保证元素唯一性的办法是判断compareTo的返回值是否为0,为0,则不进行存储。
TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparatable接口,覆盖其中的compareTo
方法,这种方式也称为元素的自然排序,或者叫做默认排序
例:
/*TreeSet_lastOne*/
import java.util.*;
class Student implements Comparable<Student>//实现Comparable接口,是其具备自然排序性
{
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;
}
public int compareTo(Student s1)//重写compareTo方法,按年龄排序
{
int num = new Integer (this.age).compareTo(s1.age);
if (num == 0)
return this.name.compareTo(s1.name);//如果第一个条件为0,则比较第二个条件
return num;//返回值
}
}
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("czhangsan",21));
ts.add(new Student("alisi",24));
ts.add(new Student("dwangwu",22));
ts.add(new Student("bzhaoliu",23));
for(Student stu: ts)
{
System.out.println("Name:"+stu.getName()+"::age :"+stu.getAge());
}
}
}
TreeSet第二种排序方式
当元素本身不具备比较性时,或者具备的比较性不是所需要的,这时需要让集合自身具备
比较性,在集合初始化时,就有了比较方式
步骤:定义比较器(比较器:定义一个类,实现Comparator接口,覆盖compare方法),
将比较器对象作为参数传递给TreeSet集合的构造函数
两种比较方式都存在,以比较器为主
例:
/*TreeSet_Comparator*/
import java.util.*;
class 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;
}
}
class Comp implements Comparator<Student>//创建比较器
{
public int compare(Student s1,Student s2)//实现compare()方法,接收两个对象进行比较
{
int num = s1.getName().compareTo(s2.getName());
if(num == 0)
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
return num;
}
}
class TreeComp
{
public static void main(String[] args)
{
TreeSet<Student> ts = new TreeSet<Student>(new Comp());
ts.add(new Student("czhangsan",21));
ts.add(new Student("dzhangsan",20));
ts.add(new Student("azhangsan",26));
ts.add(new Student("ezhangsan",22));
ts.add(new Student("bzhangsan",23));
Iterator<Student> it = ts.iterator();
while (it.hasNext())
{
Student stu = it.next();
System.out.println("Name: "+stu.getName()+" Age: "+stu.getAge());
}
}
}
泛型
JDK1.5版本以后出现的新特性,用于解决安全问题,是一个安全机制
1、将运行时期出现问题ClassCastException异常转移到了编译时期,方便于程序员解决问题
让运行时期减少安全问题
2、避免了强制转换的麻烦
泛型格式:通过<>来定义要操作的引用数据类型
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可
Collections集合框架工具类
①排序sort
public static <T extends Comparable<? super T>> void sort(List<T> list)
接收一个集合,其元素必须具有比较性(必须继承Comparable),进行排序
public static <T> void sort(List<T> list,Comparator<? super T> c)
接收一个结合,并传入一个比较器,进行排序
——————————————
②最大值max
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
根据元素的自然顺序,返回给定 collection 的最大元素。collection 中的所有元素都必须实现
Comparable 接口。
public static <T> T max(Collection<? extends T> coll,Comparator<? super T> comp)
根据指定比较器产生的顺序,返回给定 collection 的最大元素。collection 中的所有元素
都必须可通过指定比较器相互比较
——————————————
③二分查找binarySearch
public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)
使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自
然顺序对列表进行升序排序(通过 sort(List) 方法)。
list - 要搜索的列表。
key - 要搜索的键。
如果搜索键包含在列表中,则返回搜索键的索引;否则返回 (-(插入点) - 1)。插入点
被定义为将键插入列表的那一点:即第一个大于此键的元素索引;如果列表中的所有元素都
小于指定的键,则为 list.size()。注意,这保证了当且仅当此键被找到时,返回的值将 >= 0。
——————————————
④替换replaceAll
public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)
使用另一个值替换列表中出现的所有某一指定值。更确切地讲,使用 newVal 替换
list 中满足 (oldVal==null ? e==null : oldVal.equals(e)) 的每个 e 元素。(此方法对列表的大小没有任何影响。)
参数:
list - 在其中进行替换的列表。
oldVal - 将被替换的原值。
newVal - 替换 oldVal 的新值。
返回:
如果 list 包含一个或多个满足 (oldVal==null ? e==null : oldVal.equals(e)) 的 e 元素,则返回 true。
——————————————
⑤反转reverse
public static void reverse(List<?> list)
——————————————
⑥逆转比较器reverseOrder
public static <T> Comparator<T> reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
(自然顺序是通过对象自身的 compareTo 方法强行排序的。)此方法允许使用单个语句,以逆自然顺序对实现了
Comparable 接口的对象 collection(或数组)进行排序(或维护)。例如,假设 a 是一个字符串数组。那么:
Arrays.sort(a, Collections.reverseOrder());
将按照逆字典(字母)顺序对数组进行排序。
返回的比较器是可序列化的。
返回:
返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。
public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)
返回一个比较器,它强行逆转指定比较器的顺序。如果指定比较器为 null,则此方法等同于 reverseOrder()
(换句话说,它返回一个比较器,该比较器将强行逆转实现了 Comparable 接口的对象 collection 的自然顺序)。
返回的比较器是可序列化的(假设指定的比较器也是可序列化的或者为 null)。
返回:
强行逆转指定比较器顺序的比较器。
——————————————
⑦线程同步集合
synchronizedCollection(Collection<T> c)
返回指定 collection 支持的同步(线程安全的)collection。
synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表。
synchronizedMap(Map<K,V> m)
返回由指定映射支持的同步(线程安全的)映射。
synchronizedSet(Set<T> s)
返回指定 set 支持的同步(线程安全的)set。
synchronizedSortedMap(SortedMap<K,V> m)
返回指定有序映射支持的同步(线程安全的)有序映射
synchronizedSortedSet(SortedSet<T> s)
返回指定有序 set 支持的同步(线程安全的)有序 set。
数组工具类Arrays
asList:数组转换成集合
public static <T> List<T> asList(T... a)返回一个受指定数组支持的固定大小的列表。
(对返回列表的更改会“直接写”到数组。)此方法同 Collection.toArray() 一起,
充当了基于数组的 API 与基于 collection 的 API 之间的桥梁。返回的列表是可序列化的,
并且实现了 RandomAccess。此方法还提供了一个创建固定长度的列表的便捷方法,该列表被初始化为包含多个元素:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
参数:
a - 支持列表的数组。
返回:
指定数组的列表视图。
例:
/*数组变集合*/
import java.util.*;
import static java.util.Arrays.*;
import static java.lang.System.*;
class ArrCast
{
public static void main(String[] args)
{
String[] arr = {"zhangsan","lisi","wangwu","zhaoliu"};
out.println(Arrays.toString(arr));
List<String> list = asList(arr);
out.println(list);
}
}
这样做的好处是,可以使用集合的思想和方法来操作数组中的元素
注意:将数组变集合,不可以使用集合的增删方法,因为数组的长度是固定的
集合变数组
Collection接口中的toArray方法
1.指定类型的数组长度要定义多少呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,
长度为集合的size.
当指定类型的数组长度大于了集合的size,就不会创建新的数组,而是使用传递进来的
数组,所以创建一个刚刚好的数组最优。
2.为了限定对元素的操作,不需要进行增删操作
例:
/*集合变数组*/
import java.util.*;
class CollCast
{
public static void main(String[] args)
{
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(1234);
al.add(44);
al.add(655);
al.add(7563);
System.out.println(al);
Integer[] arr = al.toArray(new Integer[al.size()]);//数组的长度为集合的长度
System.out.println(Arrays.toString(arr));
}
}
Map集合
该集合存储键值对,一对一对往里存,而且要保证键的唯一性
Map
|——HashTable:底层是哈希表数据结构,不可以存入空值和空键,该集合是线程同步的(JDK1.0出现,效率较低)
|——HashMap:底层是哈希表数据结构,允许使用空值和空键,该集合是线程不同步的(JDK1.2出现,效率高)
|——TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键排序,和Set很像,Set底层就是
使用了Map集合
Map<K,V> k = key; V= value
Map集合共性方法
1.添加
put(K key,V value)
putAll(Map<? extends K,? extends V> m)
2.删除
clear()
remove(Object Key)
3.判断
contains Value(Object Value)
contains Key(Object Key)
isEmpty()
4.获取
get(Object Key)
size()
values()
entrySet()
keySet()
例:
/*Map__共性方法*/
import java.util.*;
class MapDemo
{
public static void main(String[] args)
{
HashMap<Integer,String> hm = new HashMap<Integer,String>();
sop("put = "+hm.put(1,"zhangsan"));
sop("put = "+hm.put(1,"haha"));
hm.put(4,"lisi");
hm.put(2,"wangwu");
hm.put(3,"zhaoliu");
sop("size = "+hm.size());
sop(hm);
sop("contains02 = "+hm.containsKey(02));
sop("containsZhaoliu = "+hm.containsValue("zhaoliu"));
sop("get = "+hm.get(3));
sop(hm.values());
Collection<String> coll = hm.values();
sop("coll = "+coll);
sop(hm.remove(3));
sop(hm);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
添加元素
如果出现了添加时相同的键,那么后添加的值会覆盖原有键对应的值,并put方法会返回被覆盖的值
Map集合的两种取出方式(原理:将Map集合转成Set集合,再通过迭代器取出)
1.keySet:将Map中所有的键存入到Set集合,因为Set集合具备迭代器,所以可以迭代方式取出所有的键
再根据get方法,获取每一个键对应的值
①先获取Map集合的所有键的Set集合,KeySet()
②有了Set集合,就可以获取迭代器
③有了键可以通过map集合的get方法获取其对应的值
例:
/*Map_键值的取出*/
import java.util.*;
class MapOut
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("04","zhaoliu");
map.put("02","lisi");
map.put("03","wangwu");
map.put("01","zhangsan");
Set<String> set = map.keySet();
for(Iterator<String> it = set.iterator();it.hasNext();)
{
String i = it.next();
sop("key = "+i+",value = "+map.get(i));
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
2.entrySet
将map集合中的映射关系存入到了Set集合中,而这个关系的数据类型就是:Map.Entry
其实Entry也是一个接口,它是Map接口中的一个内部接口
Map集合被使用是因为具备映射关系
例:
/*Map__entrySet*/
import java.util.*;
class MapEntrySet
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("04","zhaoliu");
map.put("02","lisi");
map.put("03","wangwu");
map.put("01","zhangsan");
Set<Map.Entry<String,String>> set = map.entrySet();
for (Iterator<Map.Entry<String,String>> it = set.iterator(); it.hasNext() ; )
{
Map.Entry<String,String> ma = it.next();
String key = ma.getKey();
String value = ma.getValue();
sop(key+":"+value);
}
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
例:
/*Map_TreeMap,比较器形式*/
import java.util.*;
class TreeMapComp 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 TreeMapDemo
{
public static void main(String[] args)
{
TreeMap<Student,String> tm = new TreeMap<Student,String>(new TreeMapComp());
tm.put(new Student("Czhangsan",20),"beijing");
tm.put(new Student("Blisi",24),"guangzhou");
tm.put(new Student("Awangwu",21),"tianjin");
tm.put(new Student("Dzhaoliu",25),"nanjing");
Set<Map.Entry<Student,String>> entrySet = tm.entrySet();
for (Iterator<Map.Entry<Student,String>> it = entrySet.iterator(); it.hasNext() ; )
{
Map.Entry<Student,String> map = it.next();
Student stu = map.getKey();
String addr = map.getValue();
System.out.println("Name = "+stu.getName()+"..Age = "+stu.getAge()+"--Addres = "+addr);
}
}
}
TreeMap练习:
/*Map_TreeMap练习*/
/*
设计需求:给出一个字符串,统计字符串中各个字符出现的次数
要求打印形式如:a(2)b(1)c(4)d(5)
*/
import java.util.*;
class TreeMapTest
{
public static void main(String[] args)
{
String str = "dsf-0jewi*a1a_)fvcj5aek2jia";
String strCount = charCount(str);
System.out.println(strCount);
}
public static String charCount (String str)
{
char[] chs = str.toCharArray();
int count = 0;
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
for (int x = 0; x<chs.length ;x++ )
{
if(!(chs[x]>='a'&& chs[x]<='z' ||chs[x]>='A' && chs[x]<='Z'))
continue;
Integer value = tm.get(chs[x]);
if(!(value ==null))
count = value;
count++;
tm.put(chs[x],count);
count =0;
}
Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
StringBuilder sb = new StringBuilder();
for (Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator(); it.hasNext() ; )
{
Map.Entry<Character,Integer> map = it.next();
Character key = map.getKey();
Integer value = map.getValue();
sb.append(key+"("+value+"); ");
}
return sb.toString();
}
}
}//Java语言_集合框架部分结束,有错误请大家指正,谢谢。