1. 集合和数组的区别?
- 最大区别在于数组是固定长度的(即在内存中一定连续),静态存储结构,而集合是可变的长度,而这个特点让集合具有更高的实用性,比如程序运行不知道究竟需要多少对象,需要在空间不足时自动扩增容量,大大提高了存储资源的高效使用。
- 数组可以存储基本数据类型和引用数据类型,而集合存在的就是专门用来存储对象的,所以就存储对象,集合可以存储不同类型的对象,而数组只能存储一种类型对象。
- 所以当我们专门存储和操作对象时,首选集合,当需要存储基本数据类型时就考虑数组了。
2.集合体系是什么?
Collection
|--List:元素是有序的,元素可以重复。因为该集合体系有索引。
|--ArrayList:底层的数据结构使用的是数组结构。特点是查询数据快,但增删稍慢。线程不同步
|--LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
|--Vector:底层是数组数据结构,线程同步,被ArrayList替代了,因为效率低。
|--Set:元素是无序,(存入和取出的顺序不一定一致),元素不可以重复。Set集合的功能和Collection是一致的。
|--HashSet:数据结构是哈希表。线程是非同步的。
保证元素唯一性的原理:判断元素的hashCode值是否相同。
如果相同,还会继续判断元素的equals方法,是否为true。
|--TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性,即实现Comparator接口作为对象传递到集合,复写compare方法。
在集合初始化时,就有了比较方式。
Map
|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk 1.0.效率低。
|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将 hashtable替代,jdk1.2.效率高。
|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
3.迭代器
集合作为存储的容器,既然是容器,那么他的作用必然方便取出其中的数据。所以就产生了迭代器,类似与数组的遍历,迭代器是专门针对集合的遍历。
迭代器实现原理:集合有着不同的容器,虽然这些容器的数据结构不同,但是都有共性的内容,判读和取出,我们将这些共性抽取,在实现中写不同的动作细节,并把它放到集合的内部类中,提供对外的方法iterator()。
有两种写的形式,如下:
Iterator it=a1.iterator();
while(it.hasNext())
{
sop(it.next());
}
for(Iterator it=a1.iterator();it.hasNext();)
{
sop(it.next());
}
4.比较器
TreeSet,TreeMap排序两种方式
一、自然排序(元素具备比较性) 实现Comparable接口
二、比较器排序(集合具备比较性) 实现Comparator接口
import java.util.*;
class TreeSetDemo
{
public static void main(String[] args)
{
//传递比较器对象
TreeSet ts=new TreeSet(new MyCompare());
ts.add(new Student("lisi02",23));
ts.add(new Student("lisi06",22));
ts.add(new Student("lisi09",29));
ts.add(new Student("lisi06",21));
Iterator it=ts.iterator();
while(it.hasNext())
{
Student stu=(Student)it.next();
System.out.println(stu.getName()+"::"+stu.getAge());
}
}
}
//让元素自身具备比较性,重写compareTo方法
class Student implements 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(Object obj)
{
//return 0;
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s=(Student)obj;
System.out.println(this.name+".....compareto......"+s.name);
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
}
}
//定义一个类,实现Comparator接口,覆盖compare方法。
class MyCompare implements Comparator
{
public int compare(Object o1,Object o2)
{
Student s1=(Student)o1;
Student s2=(Student)o2;
//return s1.getName().compareTo(s2.getName());
int num=s1.getName().compareTo(s2.getName());
if(num==0)
{
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}
5.集合那么多什么时候该用谁?
第一,判断是否是键值对
第二,判断是否需要排序
第三,判断是否唯一
第四,判断是否安全或高效率
/*
练习:
"sdfefjijntueojfiefj"获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2).....
通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间都有映射关系。
注意了,当发现有映射关系时,可以选择map集合。
因为map集合中存放就是映射关系。
什么使用map集合呢?
当数据之间存在这映射关系时,就要先想map集合。
思路:
1,将字符串转换成字符数组。因为要对每一个字母进行操作。
2,定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。
3,遍历字符数组。
将每一个字母作为键去查map集合。
如果返回null,将该字母和1存入到map集合中。
如果返回不是null,说明该字母在map集合已经存在并有对应次数。
那么就获取该次数并进行自增。,然后将该字母和自增后的次数存入到map集合中。覆盖调用原理键所对应的值。
4,将map集合中的数据变成指定的字符串形式返回。
*/
import java.util.*;
class MapTest3
{
public static void main(String[] args)
{
String s=charCount("aabbc2--===cdd`aerfefer");
System.out.println(s);
}
//传入一个字符串,返回一个a=1,c=2....的字符串
public static String charCount(String str)
{
char[] chs=str.toCharArray();
TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
int count = 0;
for(int x=0;x<chs.length;x++)
{
if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='Z' && chs[x]<='Z'))
continue;
Integer value=tm.get(chs[x]);
if(value!=null)
count = value;
count++;
tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱。
count = 0;
/*
if(value==null)
tm.put(chs[x],1);
else
{
value=value+1;
tm.put(chs[x],value);//覆盖原来的1,当key相同时。
}
*/
}
//System.out.println(tm);
//将集合取出来,按照指定形式存入StringBuffer中
StringBuffer sb=new StringBuffer();
Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();
while(it.hasNext())
{
Map.Entry<Character,Integer> me=it.next();
Character ch=me.getKey();
Integer value=me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}