脚本宝典收集整理的这篇文章主要介绍了Java 集合框架,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
集合结构图
Java 中集合又叫做容器,主要分为两大阵营:Collection、Map;前者用来存放单一元素,后者用来存放键值对;Collection 的主要实现接口有 List、Set、Queue;
@Test
public void test1() {
// 1. add(Object obj); 添加一个元素 注意 在Collection接口的实现类对象中
// 添加obj时,要求obj所在的类必须重写equals()方法
java.util.Collection coll = new ArrayList();
coll.add(132);
System.out.println(coll); // [132]
// 2. addAll(Collection coll); 添加一个Collection的集合的全部元素到现有的集合中
java.util.Collection coll1 = new ArrayList();
coll1.add(555);
coll1.addAll(coll);
System.out.println(coll1); // [555, 132]
// 3. int size(); 返回集合中元素的个数
System.out.println(coll.size()); // 1
System.out.println(coll1.size()); // 2
// 4. void clear(); 清空集合
coll1.clear();
System.out.println(coll1.size()); // 0
// 5. boolean isEmpty(); 判断是否为空集合
System.out.println(coll.isEmpty()); //false
System.out.println(coll1.isEmpty()); //true
// 6. boolean contains(Object obj); 底层是通过元素调用equals()方法,
// 判断是否为同一个对象
// 注意,在用contains()方法查看集合中是否有该对象时,
// 会直接调用该对象所在类的equals()方法
// 此处用String时因为String类中对equals()类进行了重写
coll.add(new String("hello"));
boolean hello = coll.contains(new String("hello"));
System.out.println(hello); //true
// 7. boolean containsAll(Collection coll);
// 底层是通过调用equals()方法,对集合里的元素挨个比较
// 判断形参coll中的所有元素是否都在当前集合中
coll1.add(555);
coll.add(555);
coll1.add(new String("hello"));
boolean b = coll.containsAll(coll1);
System.out.println(coll); // [132, hello, 555]
System.out.println(coll1); // [555, hello]
System.out.println(b); // true
// 7. boolean remove(Object obj); 通过元素的equals()方法判断
// 是否是要删除的那个元素,只会删除找到的第一个元素
coll.remove(555);
System.out.println(coll); // [132, hello]
// 8. boolean removeAll(Collection coll);取当前集合与形参里集合的差集
coll.removeAll(coll1);
System.out.println(coll); // [132]
// 9. retainAll(Collection coll);获取当前集合对象和形参里集合的交集,
// 并返回给调用者
java.util.Collection coll2 = Arrays.asList(132, 563);
coll.retainAll(coll2);
System.out.println(coll); // [132]
// 10. equals(Object obj); 比较两个集合里的元素是否一样
// 这里要注意区分 集合是否有序
// 11. hashcode(); 返回当前对象的哈希值
// 12. toArray(); 集合-->数组
Object[] objects = coll2.toArray();
System.out.println(Arrays.toString(objects));
// 13. 数组-->集合 Arrays.asList();
List list = Arrays.asList(45, 66, 48, "hello world");
System.out.println(list); //[45, 66, 48, hello world]
System.out.println("长度为:" + list.size());//长度为:4
List<String> list1 = Arrays.asList(new String[]{"hello java","你好"});
System.out.println(list1); //[hello java, 你好]
System.out.println("长度为:" + list1.size()); //长度为:2
List list3 = Arrays.asList(new int[]{1, 3, 5});
System.out.println("长度为:" + list3.size()); //长度为:1
List list4 = Arrays.asList(new Integer[]{154, 15, 33, 46});
System.out.println(list4); //[154, 15, 33, 46]
System.out.println("长度为:" + list4.size()); //长度为:4
}
Iterator 遍历集合,用于遍历 Collection 集合 注意:集合对象每次调用 iterator() 都会得到一个全新的迭代器;
通过for循环遍历 不推荐使用
for (int i = 0; i < list4.size(); i++) {
System.out.println("第"+ (i+1) +"个元素"+ iterator.next());
}
通过配合迭代器的 hasNext() 方法使用 while 循环进行遍历
hasNext() 判断下一个位置是否有元素
while (iterator.hasNext()) {
// next(),将指针下移,并输返回下移后位置上的元素
System.out.println(iterator.next());
}
List 正如我们上面提到的,元素是有序的,可重复的,底层是数组。但是也是需要重写 equals( ) 方法的,因为判断元素是否存在的时候是需要的;
基于 jdk1.7 ArrayList list = new ArrayList();
底层创建了长度为 10 的 Object [ ] 数组 ElementData,然后直接对创建好的数组进行赋值,如果不够则进行扩容(默认情况下扩容为原来的 1.5 倍),同时将原来的数组复制到新的数组当中;
基于 jdk1.8 ArrayList list = new ArrayList();
底层数组进行了初始化,Object [ ] elementData 初始化为{ } ,并没有创建长度,当第一次调用 add();添加元素时,底层才进行了创建长度为 10 的数组,并将数据添加到数组当中.后面的操作则与 jdk1.7 无异
jdk1.7 中的 ArrayList 的对象的创建类似于单例的饿汉式,而 jdk1.8 中的 ArrayList 的对象的创建类似于单例模式的懒汉式,延迟了数组的创建,节省内存;
结论:建议使用带有参数的构造器:ArrayList list = new ArrayList(int capacity);
直接初始化容量;
LinkedList list = new LinkedList();
内部声明了 Node 类型的 first 和 last 属性,默认值为 null,list.add();
将对象封装到 Node 中,创建了 Node 对象
Node 的定义体现了 LinkedList 的双向链表的说法
private static class Node<E> {
E item; // 数据
Node<E> next; // 下一个值
Node<E> prev; // 上一个值
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
总结:常用方法
// 增
add(Object obj);
// 删
remove(int index);
remove(Object obj));
// 改
set(int index,Object ele);
// 查
get(int index)
// 插
add(int index,Object ele)
// 长度
size()
// 遍历
Iterator // 迭代器
@Test
public void test() {
ArrayList list = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
list.add(new person("小红", 23, "女"));
System.out.println(list);
//[123, 556, hello, person{name='小红', age=23, sex='女'}]
}
@Test
public void test1() {
ArrayList list = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
list.add(new person("小红", 23, "女"));
System.out.println(list);// [123, 556, hello, person{name='小红', age=23, sex='女'}]
list.add(2, new person("小黄", 22, "男"));
System.out.println(list);
// [123, 556, person{name='小黄', age=22, sex='男'}, hello, person{name='小红', age=23, sex='女'}]
}
@Test
public void test2() {
ArrayList list = new ArrayList();
ArrayList list1 = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
list.add(new person("小红", 23, "女"));
list1.add(45);
list1.add(36);
list1.add(86);
System.out.println(list1); // [45, 36, 86]
list1.addAll(2, list);
System.out.println(list1);// [45, 36, 123, 556, hello, person{name='小红', age=23, sex='女'}, 86]
}
@Test
public void test3() {
ArrayList list = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
list.add(new person("小红", 23, "女"));
System.out.println(list);// [123, 556, hello, person{name='小红', age=23, sex='女'}]
System.out.println(list.get(3)); // person{name='小红', age=23, sex='女'}
}
@Test
public void test4() {
ArrayList list = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
System.out.println(list.indexOf(556)); // 1
}
@Test
public void test5() {
ArrayList list = new ArrayList();
list.add(123);
list.add(123);
list.add(556);
list.add(556);
list.add(123);
list.add("hello");
System.out.println(list.lastIndexOf(123)); // 4
}
@Test
public void test6() {
ArrayList list = new ArrayList();
list.add(123);
list.add(123);
list.add(556);
System.out.println("移除前:" + list); // 移除前:[123, 123, 556]
Object remove = list.remove(2);
System.out.println("移除的值为:" + remove); // 移除的值为:556
System.out.println("移除后:" + list); // 移除后:[123, 123]
}
@Test
public void test7() {
ArrayList list = new ArrayList();
list.add(123);
list.add(123);
list.add(556);
System.out.println("设置前:" + list); // 设置前:[123, 123, 556]
list.set(0, new person("小明", 23, "男"));
System.out.println("设置后:" + list); // 设置后:[person{name='小明', age=23, sex='男'}, 123, 556]
}
@Test
public void test8() {
ArrayList list = new ArrayList();
list.add(123);
list.add(556);
list.add("hello");
list.add(new person("小红", 23, "女"));
List list1 = list.subList(1, 3);
System.out.println(list); //[123, 556, hello, person{name='小红', age=23, sex='女'}]
System.out.println(list1); //[556, hello]
}
Set 接口是 Collection 的子接口,Set 接口没有提供额外的方法,Set 存储无序的、不可重复的数据
所以,Set是严格的
底层数据的存储依然是以数组的形式进行存储,但是无序不等于随机,当我们添加数组的时候,并不是按照数组的索引进行添加,而是根据哈希值进行添加。
针对上述的第三种情况又有:
规则,新的 hash 值相同的元素放在同一个位置的数组里,其顺序在jdk7.0/8.0中有些许不同
总结:七上八下(指的是 新元素的存放位置,七、新的元素放在原来的数组的位置(上边),旧的元素向下移动,在链表中,新的元素指向旧的元素; 八、新的元素放在链表中,在链表中,旧的指向新的)
@Test
public void test1() {
Set set = new HashSet();
set.add("hello");
set.add(123);
set.add("abc");
set.add(123);
set.add(new person("小红", 29, "男"));
set.add(new person("小红", 29, "男"));
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
输出结果
abc
person{name='小红', age=29, sex='男'}
hello
123
LinkedHashSet 是 HashSet 的子类,根据添加元素的顺序来遍历集合
@Test
public void test2() {
Set set = new LinkedHashSet();
set.add("hello");
set.add(123);
set.add("abc");
set.add(123);
set.add(new person("小红", 29, "男"));
set.add(new person("小红", 29, "男"));
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
输出结果
hello
123
abc
person{name='小红', age=29, sex='男'}
自然排序中,比较两个对象是否相同的标准为:compareTo() 返回 0 ,而不再是 equals() 方法 定制排序中,比较两个对象是否相同的标准是 compare() 但是规则是一样的
@Test
public void test3() {
//编写比较规则
Comparator comparator = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof person && o2 instanceof person) {
person p1 = (person) o1;
person p2 = (person) o2;
return p1.getName() wangt.cc pareTo(p2.getName());
} else {
throw new RuntimeException("数据异常!");
}
}
};
//应用比价规则
TreeSet treeSet = new TreeSet(comparator); //在有参数的情况下,会根据参数对象中所定义的排序方式进行排序,
// 若没有,将会按照添加的对象中实现的comparable接口后重写的compareTo();的规则进行排序
treeSet.add(new person("孔乙己", 33, "女"));
treeSet.add(new person("祥林嫂", 22, "男"));
treeSet.add(new person("鲁迅", 18, "女"));
Iterator iterator = treeSet.iterator();//通过age进行自然排序
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
输出结果:
person{name='孔乙己', age=33, sex='女'}
person{name='祥林嫂', age=22, sex='男'}
person{name='鲁迅', age=18, sex='女'}
Map,并列于 Collection 接口,用于存储双列数据(键值对 key - value)
HashMap 的底层:
数组+链表(jdk7及以前) 数组+链表+红黑树(jdk8+)
对 Map 底层原理的理解
JDK7为例说明:
HashMap map = new HashMap(); 在实例化之后,底层创建了一个长度为 16 的一维数组 Entry [ ] table。
当我们往 HashMap 中添加数据的时候 map.put(ket1,value1);
JDK8 在底层与JDK7的不同之处:
new HashMap();
底层没有创建一个长度为16的数组底层主要关键字
以上是脚本宝典为你收集整理的Java 集合框架全部内容,希望文章能够帮你解决Java 集合框架所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。