其实网上这些总结简直是多了去了,但是果然还是用自己的话总结一下比较靠谱啊~而且面试官们都贼稀罕问这些东西。我反正是尽力写的通俗易懂然后好记一点,若有疏漏或者错误……大家看着喷就好。
什么是集合框架?首先什么是集合?高中数学里好像有这么个概念,实际上它就是一个容器,我们在里面可以去存放一些数据。
一般我们最先接触的容器是数组,可以在数组里去存放你想放的数据,但是数组这东西限制挺多的,比如初始化之后长度是固定的,还有只能存放一种数据等等。而集合框架就相对灵活一些。
现实中的容器是多种多样的,集合框架中的容器类型可以分为两个大类:Collection和Map。
如果做个比喻的话,Collection就像个大箱子,可以直接把东西塞进去
而Map的话,有点像超市里的存包柜
为什么这么说呢?因为在Map里存放数据是用键值对(key-value)的形式实现的,你看你存东西的时候存包柜会给你一张密码纸,取的时候要一张密码纸对应一个柜门,而不一样的柜子里可以放一样的东西(比如一号柜子里可以放一斤大米,二号柜子也可以放一斤大米)生成的密码却不能是一样的,这就跟Map里可以存在相同的value,却不能够存在相同的key是一样的。
前面说过Collection就像一个箱子,而这个“箱子”也是分种类的。也是两个大种类下分小种类
List就像是书架,存放数据的时候就像往书架上码书,要一本一本、整整齐齐地摆上去,这样的话你就算摆了几本一样的书,也可以根据摆放的先后顺序来区分这几本书的不同;
而Set的话因为它无序,所以你放相同的东西的话取的时候是没法区分的(比如我在箱子里放了两个乒乓球,那取的时候我说把我第一次放进去的那个乒乓球拿出来鬼知道哪个球是第一次放进去的)。
在Java中,Collection、List、Set、Map都是接口,用的时候要根据具体情况去选择合适的实现类。
List接口实现类:ArrayList、LinkedList和Vector
一般我们最常用的是ArrayList,它的底层是基于数组实现的,但是线程不安全,如果想用线程安全的那就是Vector,还有一个叫LinkedList,这个底层是基于链表实现,在批量数据需要随机插入的时候选用。简单一句话就是:没有特别需求用ArrayList,需要线程安全用Vector,需要效率用LinkedList。(插入一个数据讲道理是ArrayList快些,但是纠结一个数据快不快的没什么意义吧)
然后看一下最基本的操作吧,容器的操作无非是数据的增、删、改、查:
//随便写一个类
public class Apple {
private String color;
private double Weight;
private String type;
public Apple(String color, double weight, String type) {
super();
this.color = color;
Weight = weight;
this.type = type;
}
}
public class TestCollection {
public static void main(String[] args) {
Apple ap1=new Apple("red", 0.36, "脆");
Apple ap2=new Apple("green", 0.25, "面");
Apple ap3=new Apple("yellow", 0.29, "面");
Apple ap4=new Apple("red", 1.1, "脆");
//List list=new ArrayList<>();
List list=new LinkedList<>();
// List list=new Vector<>();
list.add(ap1);
list.add(ap2);//普通的增加操作
list.remove(ap1);//普通的删除操作
list.set(1, ap3);//普通的修改操作,前面那个参数是个下标,类似数组
list.get(0);//普通的查询操作,参数是下标
}
}
当然我们流弊的Collection不能就这么几个基本功能这么low,其他功能比如:
嗯,官方解释比我水平不知道高到哪里去了,我建议大家自己看。◕‿◕。
这里需要说明一点,这里的无序是指不像数组那样有下标,也不像List有个index,和下文中TreeSet里面那个元素顺序不是一个概念
两个实现类:HashSet 和TreeSet;
HashSet的话,基本用法和List差不多,但是有以下三个特点:
元素可以是null(但是因为第一条元素不能重复,所以只能有一个null)
然后是TreeSet:
我觉得TreeSet是一个挺屌的东西,因为你把元素放进去它会自动给你排序,来吧咱们试一下,用字符串试好了:
Set set=new TreeSet<>();
set.add("What????");
set.add("hello");
set.add("ohyes");
set.add("ahhhhhhh!!!");
set.add("I Wanne sleep");
Iterator it=set.iterator();
while(it.hasNext())
{Object str=it.next();
System.out.println(str);
}
然后是打印结果:
I Wanne sleep
What????
ahhhhhhh!!!
hello
ohyes
可以看到,TreeSet把里面的元素按照A~Z,然后a~z的顺序自动排了一遍;
其实这货还可以自定义排序的规则,这就需要你在需要存的那个类里面实现Comparator接口的类CustomerComparator, 当表达式compare(x,y)的值大于0,表示x大于y,小于0,表示x小于y,等于0,表示x等于y,拿上面那个苹果类举例:
public class Apple implements Comparator{
private String color;
private double Weight;
private String type;
@Override
public int compare(Object o1, Object o2) {
Apple a1=(Apple)o1;
Apple a2=(Apple)o2;
if(a1.getWeight()>a2.getWeight()){return -1;}
if(a1.getWeight()return 1;}
return 0;
}
其中get和set方法还有构造器和ToString方法就不放上来了。上面这段代码是让Apple类根据重量(weight)进行降序排序,然后咱们试下效果:
Apple ap1=new Apple("red", 0.36, "脆");
Apple ap2=new Apple("green", 0.25, "面");
Apple ap3=new Apple("yellow", 0.29, "面");
Apple ap4=new Apple("red", 1.1, "脆");
//这里要调用Apple类的构造器
Set set=new TreeSet<>(new Apple());
set.add(ap1);
set.add(ap2);
set.add(ap3);
set.add(ap4);
Iterator it=set.iterator();
while(it.hasNext())
{Object apple=it.next();
System.out.println(apple);
}
然后下面是打印结果:
Apple [color=red, Weight=1.1, type=脆]
Apple [color=red, Weight=0.36, type=脆]
Apple [color=yellow, Weight=0.29, type=面]
Apple [color=green, Weight=0.25, type=面]
嗯,Set大概就是这样。
map是以键值对存放数据,像这样:
Map map=new HashMap<String,Apple>();
map.put("昨天买的", ap1);
键值对中的键(key)实际上是一个标记,有点像数组的下标,但是这个标记可以是你定义的任何类型,类似于一个“信物”。做个比喻的话,就好像你去存东西,然后取的时候要确认身份怎么办呢?就要在存的时候约定好一个信物,这个信物必须是独一无二的否则别人就可能会把你存放的东西拿走。
然后是HashMap和TreeMap的区别,这个和HashSet与TreeSet的区别一样,带Tree的都是可以自动排序或者自定义排序的,不过TreeMap排序的基准是按着Key来的也就罢了。
一个是泛型:
简单说就算我在容器上贴了个标签,这容器只能放这种类型的对象:
List list1=new ArrayList<Apple>();//只能放苹果
List list2=new LinkedList<String>();//只能放字符串
List list3=new Vector<Integer>();//只能放整数
Map map1=new HashMap<String,Apple>();//用字符串做信物存取苹果
Map map2=new HashMap<Apple,String>();//用苹果做信物存取字符串
主要是起到一个规范作用,可以提高效率
还有就是迭代器(Iterator):
迭代器是用来遍历集合的,前面的代码实际上用到了
list l = new ArrayList();
l.add("aa");
l.add("bb");
l.add("cc");
for (Iterator iter = l.iterator(); iter.hasNext();) {
String str = (String)iter.next();
System.out.println(str);
}
Iterator iter = l.iterator();
while(iter.hasNext()){
String str = (String) iter.next();
System.out.println(str);
}
Collection的内容基本想到的就这些,简单总结一下的话大概是这样:
集合框架本质上是容器;
分成需要信物存取(Map)和不需要信物存取的(Collection);
不需要信物的(Collection)常用的有两种接口:
有序可重复的List和无序不能重复的Set;
List有三个实现类,正常用ArrayList,需要存大批量随机数据用LinkedList,需要线程安全用Vector;
Set有俩实现类,正常用HashSet,需要个顺序的话用TreeSet;
需要信物存取的(Map)常用的两个实现类:
正常用HashMap,需要个顺序用TreeMap;