java集合的个人理解和整理
Java集合的种类
java集合是什么,个人的理解是有一个存放数据的容器,这个数据可以是引用类型,基本类型(要使用包装类)。
两大类collection,map
个人认为集合存储数据的形式为2种,一种是value,另一种为key - value.
collection这个接口下有3大接口 list,set,queue。
另外加上map这个key-value接口。这个4种集合是我们用的计较多的。
如果只是简单想要知道怎么用的话,百度一大把这些接口的方法使用。但是如果想详细了解的话,就需要你对数据结构有些了解。数组,字符串,链表,树,队,栈。这里就不详细说了,百度下把。一大把。
给大家分享一个截图把https://blog.csdn.net/u010887744/article/details/50575735
老哥贼牛逼!如果你都用过并且理解原理的话,Java集合将成为你的垫脚石。(对于小胡还是一个绊脚石,共勉)
Java常用的集合
collection之list(重中之重)
在图中我们能看到list接口的实现类有linkedlist,Arraylist,vector,stack.
个人不建议使用Vector和stack,最最重要的原因是太古老了,而且已经有替代品了。仔细看图中方法和类名。(继承是实线,接口是虚线),
但是你还是要清楚Vector与Arraylist的区别。
两者最大的区别是一个多线性安全,vector类中有大量的方法使用了同步锁(synchronized),那么效率就比不上Arraylist.如果还要问你还有什么区别的话,两者在拓展数组(容器,不是list.size())大小的时候增加的方式不一样。
linkedlist,Arraylist两者的区别在于他们底层实现的数据结构。一个链表实现,一个是数组实现。数组和链表有什么优缺点就是这个2个实现类之间的优缺点
arraylist
从名字我们可以知道它的底层是用Arraylist,也是我们用的比较多的一种list实现类了。
// An highlighted block
//常用的命名构造方法创建实例
List<String> list1 =new ArrayList<>();
List<String> list2 =new ArrayList<>(2);
List<String> list3 = new ArrayList<>(list2);
这3种方式,无参,参数int, collection接口实现类。Arraylist这3个构造方法的源代码也很简单,无参会先赋值一个“{}”的数组,int类型就会先判断这个int的值,>0还是<0 =0,>0就赋值object[int],=0 就赋值{};小于0就抛出异常。 collection接口实现类形式的构成方法,就会先通过toArray()转换成一个object[]数组也是和int类型的构造方法一样。只不过这个object数组中有值,Arrays.copyOf()这静态方法复制过去。
到这也有了一个初步的了解了,介绍一下常用的方法把。
add()方法
list.add("111");
list.add(1,"111");
第一种表示添加,在末尾加上这个元素。第二种表示插入(变相的添加)指定位置插入这个元素。
get()方法
Stirng s = list.get(1);
表示获取指定位置的值。
set()
String s = list.set(1,"222");
表示将1的位置的元素值改为"222",并且将原有的值返回。
remove()方法
list.remove(1);
list.remove("222");
这个两种方法一个表示通过下标去删除元素,一个通过元素,删除元素。
这个里有一个坑,你如你没有注意的话,如果你用的List 的话,这里你要删除的话他会默认使用下标的方式,如果通过内容去删除元素,list.remove((Integer) 1)需要显示声明。
clear()方法表示清空集合
contains(Object o)表示是否含有这个元素
list.iterator()方法:collection继承了Iterator类,该类表示迭代,可以理解为需要遍历的时候可以使用这个方法。
linkedlist
linkedlist在功能上与Arraylist是一样的,功能上就不重复说明了,那么他们的区别在哪了呢,上面我也提到了,linkedlist的底层是链表,链表和数组的区别就他们之间的区别,就可以判断在不同场景的去选择使用Arraylist,Linkedlist.
Collection之set
set和list的区别在于list添加元素是有序,元素可以重复,set添加元素是无序,元素不能重复。知道这一点基本上也懂了set的用法了
hashset
对于hashset,个人的一个理解可以当作是hashmap,这样你对hashset的使用将得心应手。将set的元素理解成hashmap的键值对.功能方法就详细解释了。
Treeset
留一个坑吧,使用红黑树,对set的值能有一个排序。默认升序。
LinkedHashSet
留一个坑吧,使用双向链表来维护插入元素的顺序。
Map
1.map是一种k-v的形式保存,Map用于保存具有映射关系的数据。
2.了解map是怎么存储k-v,就需要先了解hashcode这个方法的含义。个人理解:hash值对对象相关的信息(对象地址,对象信息)一个映射。
hashmap
hashmap可以说是我们用的比较的多的一个Map实现类。
hashmap的底层数据结构是什么呢,哈希表,什么哈希表了
HashMap由数组+链表+红黑树组成的,数组是HashMap的主体。我们先分析下为什么要用数组+链表+红黑树的形式呢,假如我存一个key为3 value为”abc“,怎么存,按照key的大小轮流插入末尾?但是key可以为任意类型,随机存?,那怎么取呢。前面我提到了hashcode就是一个比较好解决方法,key.hashcode()通过key内容与map(信息,长度)生成一个”映射地址“,通过这个映射就找到地址,(hashcode()通常返回对象地址)。
比如我现在有 0 1 2 3 4 5 6 7 ,8个内存地址
那么我们就定义我们的hashcode 为key%8,然后把我们的类存放在取得得余数那个位置。比如我们的key为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果key是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过key除 8求余数直接找到存放的位置了。 hashcode()当然不会这么简单。我理解为通过key的hashcode就能准确知道存储的地址了。
关于链表又有什么用呢,使用hashcode会导致哈希冲突,2个不同的key,肯能对映射同一个地址,那么这个时候该存什么,替代原来的元素?肯定是不行的,解决哈希冲突有很多种方式,java的hashmap采用的是链地址法,
这样也会有一缺陷,如果链表太长,有多的话,那么hashmap的性能就会很低。这个时候就引入了红黑树,红黑树是一种平衡二叉查找树,可以去百度下。如果链表大于等于8的时候就会转换成红黑树,树的查找的次数不会大于树的高度。效率就大大提升。(下面还会进一步详细解释。)
hashmap常用的方法
这里推荐一个网站
https://www.cnblogs.com/jiuhaoyun/p/8985643.html
需要知道map中contains,被分成2种containskey,containsvalue
hashmap的遍历
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
map.put("4", "value4");
//第一种:普通使用,二次取值
System.out.println("\n通过Map.keySet遍历key和value:");
for(String key:map.keySet())
{
System.out.println("Key: "+key+" Value: "+map.get(key));
}
//第二种
System.out.println("\n通过Map.entrySet使用iterator遍历key和value: ");
Iterator map1it=map.entrySet().iterator();
while(map1it.hasNext())
{
Map.Entry<String, String> entry=(Entry<String, String>) map1it.next();
System.out.println("Key: "+entry.getKey()+" Value: "+entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("\n通过Map.entrySet遍历key和value");
for(Map.Entry<String, String> entry: map.entrySet())
{
System.out.println("Key: "+ entry.getKey()+ " Value: "+entry.getValue());
}
//第四种
System.out.println("\n通过Map.values()遍历所有的value,但不能遍历key");
for(String v:map.values())
{
System.out.println("The value is "+v);
}
}
hashtable
关于hashtable正在功能上与hashmap没有区别,但是他们最大的区别在于hashtable是多线性安全的,建议不要再使用,以为这个类比较古老,现在也有了替代品concurrenthashmap并发hashmap,功能上就不继续深入。
treemap
留一个坑吧,使用红黑树,TreeMap的Key有序的。
linkedhashmap
留一个坑吧,LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序。所有他保证了插入的顺序。我的理解为再原来entry 加上了一个前驱,和后驱。让他这个元素put时候,上一次添加的元素后期指向当前元素,当前元素的前驱指向上一个元素。
总结下吧
虽然还有许多的集合特点没有说明,这篇文章我希望是一个入门的知识,后续也会将自己对集合的理解进步描述。你需要掌握hashset,arraylist,hashmape