集合又称为容器,它是一个对象,专门用来管理一组其他对象。具体地说,集合对象可以用来存储、检索、操作和统计一组其他对象。在集合内的对象称之为元素。
为什么会出现集合类呢?
面向对象的语言对事物的体现都是以对象的形式,所以为了方便更多的对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合类同是容器,有什么不同?
数组虽然也可以存储对象,但长度是固定的,集合长度是可变的;数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
集合框架中主要接口和常用实现类的层次结构如下图:
Java集合框架总结
因为每一个容器对数据的存储方式不同,所以出现了如此多的容器。
最顶层的Collection接口声明了一组管理其存储的元素的方法。最常用的有下面几类:
1、 boolean add(E e)添加对象,它的参数类型属于泛型,可以接收任意数据类型。
2、 boolean remove(Object o)删除对象
3、 int size()返回集合中元素的数量
4、 boolean isEmpty()判断集合是否为空
5、 boolean contains(Object o)判断集合中是否含有指定元素
6、 Iterator iterator()返回集合元素的迭代器
在以上的方法中,第6个的迭代器实际就是取出集合元素的一种方式。它从前到后把集合中所有的元素都访问一遍,它声明的主要方法有:
1、 boolean hasNext()判断是否还有元素可以迭代
2、 E next()返回迭代的下一个元素
Collection集合中存储的都是对象的引用。
List集合:元素是有序的,可以重复;Set集合:元素是无序的,不可以重复。
List接口的实现类有ArrayList、LinkedList、Vector,这三者的特点是:
ArrayList的底层数据结构是动态数组结构,对元素的查询效率很高,但是对元素的插入或删除速度很慢;
LinkedList的底层数据结构是双向链表数据结构,它针对频繁的插入或删除元素的操作时效率很高,但不适合快速的随机访问某个位置的元素。
Vector内部也是使用动态数组来存储对象的,提供的操作方法几乎跟ArrayList一样,可以看成是旧版的ArrayList类。
Vector和ArrayList不同的是,它提供了一个返回元素是枚举(Enumeration)对象的elements方法,它和Iterator类似。另外,Vector是同步的,线程安全的;而ArrayList是不同步的,即线程不安全的。如果不需要考虑线程的话,一般使用ArrayList。
另外,LinkedList具有一些特殊的方法:addFirst、removeFirst等方法,利用这些方法,我们可以模拟一个队列或是堆栈的数据结构。
我们知道ArrayList中的元素是有序可以重复的,那么如果想去除重复元素的话,可以通过定义一个临时容器ArrayList来实现。
Set接口的实现类有HashSet、TreeSet。
HashSet底层的数据结构是哈希表,线程不同步;TreeSet的底层数据结构是二叉树,支持元素的自然排序。
注意:List集合判断元素是否相同或者是移除元素,依据的是元素的equals方法;
HashSet集合判断元素是否存在及删除操作时,依赖的是元素的hashCode和equals方法
Comparable接口和Comparator接口
java.lang.Comparable接口会强行对实现它的每个类的对象进行整体排序,也就是类的自然排序。所以它适用于一个类有自然顺序的时候,但是它有局限性,一个类只能实现该接口一次,即只能定义一种自然排序的规则。
Comparable接口方法:int compareTo(T o)
利用Comparable接口创建自定义类的排序顺序,只要实现compareTo()方法即可。通常都是依赖几个数据成员的自然排序。同时类也应该覆盖equals()和hashCode()以确保两个相等的对象返回同一个哈希码。
Comparator接口方法:int compare(T o1, T o2)
如果想让排序集合使用不同的比较方法,可以将一个实现Comparator接口的类的对象(自定义的比较器)传递给排序集合的构造器。
Map接口:它定义了存储键/值对的方法,其中“键”是唯一的。可以根据“键”和它相对应的一个“值”。和Set集合基本类似。
Map接口的实现类有Hashtable、HashMap、TreeMap,三者的特点是:
Hashtable底层是哈希表数据结构,不可以存入null键和null值,线程同步。
HashMap底层是哈希表的数据结构,允许使用null键和null值,和Hashtable类大致相同,该集合是不同步的。
TreeMap底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序。
import java.util.*;
class MapTest2
{
public static void main(String[] args)
{
String s=charCount("+ade--aac,+,-d-efa");
String[] s1=s.split(" ");
for(int i=0; i
{
System.out.print(s1[i]); //得到打印结果:a4c1d2e2f1
}
}
public static String charCount(String s)
{
TreeMap tm= new TreeMap();
char[] c=s.toCharArray();//转换为字符数组
int count=0;
for(int x=0 ;x //遍历字符数组
{
if(!(c[x]>='a' && c[x]<='z' || c[x]>='A' && c[x]<='Z'))
continue;
Integer value= tm.get(c[x]); //获得与键对应的值,如果没有找到,则返回null
if(value!=null)
count=value;
count++;
tm.put(c[x],count); //将字母和次数存入map集合中
count=0;//找下一个字母之前,对此次操作清零
}
StringBuilder sb=new StringBuilder();
Set> entrySet=tm.entrySet(); //使用map集合中的entrySet方法
Iterator> it=entrySet.iterator();
while(it.hasNext())
{
Map.Entry me=it.next();
Character ch=me.getKey();
Integer value=me.getValue();
sb.append(ch+" "+value+" "); //将键/值对存入缓冲区
}
return sb.toString();
}
}
为什么会出现集合类呢?
面向对象的语言对事物的体现都是以对象的形式,所以为了方便更多的对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合类同是容器,有什么不同?
数组虽然也可以存储对象,但长度是固定的,集合长度是可变的;数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
集合框架中主要接口和常用实现类的层次结构如下图:
Java集合框架总结
因为每一个容器对数据的存储方式不同,所以出现了如此多的容器。
最顶层的Collection接口声明了一组管理其存储的元素的方法。最常用的有下面几类:
1、 boolean add(E e)添加对象,它的参数类型属于泛型,可以接收任意数据类型。
2、 boolean remove(Object o)删除对象
3、 int size()返回集合中元素的数量
4、 boolean isEmpty()判断集合是否为空
5、 boolean contains(Object o)判断集合中是否含有指定元素
6、 Iterator iterator()返回集合元素的迭代器
在以上的方法中,第6个的迭代器实际就是取出集合元素的一种方式。它从前到后把集合中所有的元素都访问一遍,它声明的主要方法有:
1、 boolean hasNext()判断是否还有元素可以迭代
2、 E next()返回迭代的下一个元素
Collection集合中存储的都是对象的引用。
List集合:元素是有序的,可以重复;Set集合:元素是无序的,不可以重复。
List接口的实现类有ArrayList、LinkedList、Vector,这三者的特点是:
ArrayList的底层数据结构是动态数组结构,对元素的查询效率很高,但是对元素的插入或删除速度很慢;
LinkedList的底层数据结构是双向链表数据结构,它针对频繁的插入或删除元素的操作时效率很高,但不适合快速的随机访问某个位置的元素。
Vector内部也是使用动态数组来存储对象的,提供的操作方法几乎跟ArrayList一样,可以看成是旧版的ArrayList类。
Vector和ArrayList不同的是,它提供了一个返回元素是枚举(Enumeration)对象的elements方法,它和Iterator类似。另外,Vector是同步的,线程安全的;而ArrayList是不同步的,即线程不安全的。如果不需要考虑线程的话,一般使用ArrayList。
另外,LinkedList具有一些特殊的方法:addFirst、removeFirst等方法,利用这些方法,我们可以模拟一个队列或是堆栈的数据结构。
我们知道ArrayList中的元素是有序可以重复的,那么如果想去除重复元素的话,可以通过定义一个临时容器ArrayList来实现。
Set接口的实现类有HashSet、TreeSet。
HashSet底层的数据结构是哈希表,线程不同步;TreeSet的底层数据结构是二叉树,支持元素的自然排序。
注意:List集合判断元素是否相同或者是移除元素,依据的是元素的equals方法;
HashSet集合判断元素是否存在及删除操作时,依赖的是元素的hashCode和equals方法
Comparable接口和Comparator接口
java.lang.Comparable接口会强行对实现它的每个类的对象进行整体排序,也就是类的自然排序。所以它适用于一个类有自然顺序的时候,但是它有局限性,一个类只能实现该接口一次,即只能定义一种自然排序的规则。
Comparable接口方法:int compareTo(T o)
利用Comparable接口创建自定义类的排序顺序,只要实现compareTo()方法即可。通常都是依赖几个数据成员的自然排序。同时类也应该覆盖equals()和hashCode()以确保两个相等的对象返回同一个哈希码。
Comparator接口方法:int compare(T o1, T o2)
如果想让排序集合使用不同的比较方法,可以将一个实现Comparator接口的类的对象(自定义的比较器)传递给排序集合的构造器。
Map接口:它定义了存储键/值对的方法,其中“键”是唯一的。可以根据“键”和它相对应的一个“值”。和Set集合基本类似。
Map接口的实现类有Hashtable、HashMap、TreeMap,三者的特点是:
Hashtable底层是哈希表数据结构,不可以存入null键和null值,线程同步。
HashMap底层是哈希表的数据结构,允许使用null键和null值,和Hashtable类大致相同,该集合是不同步的。
TreeMap底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序。
import java.util.*;
class MapTest2
{
public static void main(String[] args)
{
String s=charCount("+ade--aac,+,-d-efa");
String[] s1=s.split(" ");
for(int i=0; i
{
System.out.print(s1[i]); //得到打印结果:a4c1d2e2f1
}
}
public static String charCount(String s)
{
TreeMap tm= new TreeMap();
char[] c=s.toCharArray();//转换为字符数组
int count=0;
for(int x=0 ;x //遍历字符数组
{
if(!(c[x]>='a' && c[x]<='z' || c[x]>='A' && c[x]<='Z'))
continue;
Integer value= tm.get(c[x]); //获得与键对应的值,如果没有找到,则返回null
if(value!=null)
count=value;
count++;
tm.put(c[x],count); //将字母和次数存入map集合中
count=0;//找下一个字母之前,对此次操作清零
}
StringBuilder sb=new StringBuilder();
Set> entrySet=tm.entrySet(); //使用map集合中的entrySet方法
Iterator> it=entrySet.iterator();
while(it.hasNext())
{
Map.Entry me=it.next();
Character ch=me.getKey();
Integer value=me.getValue();
sb.append(ch+" "+value+" "); //将键/值对存入缓冲区
}
return sb.toString();
}
}