首页 文章 精选 留言 我的

精选列表

搜索[容器配置],共10000篇文章
优秀的个人博客,低调大师

Java容器深入浅出之List、ListIterator和ArrayList

List是Collection接口的子接口,表示的是一种有序的、可重复元素的集合。 List接口的主要实现类ArrayList和Vector,底层都是维护了一套动态的,可扩展长度的Object[]数组,通过initialCapacity参数来动态地调整长度。因此,相比较父接口Collection所提供的公共增删改方法,List接口及实现类也定义了通过索引来增删查改元素,或者基于元素查找索引的方法。更一般地,ArrayList中的元素可以为null。 List及List新增的ListIterator接口 List接口的定义方法如下 1 public class TestList { 2 3 @SuppressWarnings("unlikely-arg-type") 4 public static void main(String[] args) { 5 6 List<String> books = new ArrayList<>(); 7 //List集合添加元素的顺序是有序的 8 books.add(new String("资本论")); 9 books.add(new String("***宣言")); 10 books.add(new String("家庭私有制和国家的起源")); 11 System.out.println(books); 12 //add和addAll分别在指定索引处添加元素或另一个集合 13 books.add(1, "德意志意识形态"); 14 books.forEach(str -> System.out.println(str)); 15 //使用Lambda表达式对List进行排序 16 books.sort((o1, o2) -> (o1.length() - o2.length())); 17 System.out.println(books); 18 //删除指定索引的元素 19 books.remove(2); 20 System.out.println(books); 21 //通过指定索引返回元素(==根据HashCode来判断,此处返回false) 22 System.out.println(books.get(0) ==new String("资本论")); 23 //通过indexOf来返回指定元素所在的索引位置 24 //indexOf通过元素的equals方法来判断, 只要是true就返回对应的索引 25 System.out.println(books.indexOf(new String("德意志意识形态"))); 26 //通过索引改变元素 27 books.set(1, new String("神圣家族")); 28 //返回子集合[1,3), 不改变原集合 29 System.out.println(books.subList(1, 3)); 30 31 //使用Lambda表达式使用每个字符的长度替代原集合的元素 32 books.replaceAll(ele -> ele.length() + ""); 33 //因为A对象equals方法恒返回true,所以集合会在第一次比较中直接删除第一个元素 34 books.remove(new A()); 35 System.out.println(books); 36 //同样的,继续删除第一个元素 37 books.remove(new A()); 38 System.out.println(books.size()); 39 40 } 41 42 } 43 44 class A{ 45 //定义A类对象的equals方法恒返回true 46 public boolean equals(Object obj) { 47 return true; 48 } 49 } 与Set集合不同,List集合新增了一个继承Iterator接口的子接口ListIterator接口,可以实现反向迭代和增加元素的功能。 1 /* 2 * 与Collection集合的Iterator接口不同, List额外提供一个ListIterator接口(继承了Iterator接口), 增加了如下三个方法: 3 * 1. hasPrevious():是否还有上一个元素 4 * 2. previous():返回上一个元素 5 * 3. add():增加一个元素 6 */ 7 public class ListIteratorTest { 8 9 public static void main(String[] args) { 10 11 String[] books = { 12 "资本论","德意志意识形态","***宣言" 13 }; 14 List<String> booksList = new ArrayList<>(); 15 for(int i=0; i<books.length;i++) { 16 booksList.add(books[i]); 17 } 18 ListIterator<String> lit = booksList.listIterator(); 19 System.out.println("====下面开始正向迭代===="); 20 while(lit.hasNext()) { 21 System.out.println(lit.next()); 22 lit.add("----分隔符----"); 23 } 24 System.out.println("====下面开始反向迭代===="); 25 while(lit.hasPrevious()) { 26 System.out.println(lit.previous()); 27 } 28 29 } 30 31 } ArrayList和Vector 如前所述,ArrayList和Vector底层维护了一个动态可变的对象数组。如果创建对象时不指定容量值,会有一个默认的数组长度10。更一般地,可以通过在创建对象时指定容量值: 1. void ensureCapacity(int minCapacity):将List集合数组长度增加到minCapacity。如可提前知道元素个数,可以赋值长度,以减少频繁扩容所带来的性能开销。 2. void trimToSize():调整数组长度至当前元素的个数,以节省空间。 ArrayList与Vector相比较,需要注意以下几点: 1. ArrayList是线程不安全的,因此性能较高;Vector是线程安全的,但性能较差;后面的博文会介绍如果通过Collection提供的工具类,使ArrayList线程安全。 2. Vector及其子类Stack,是非常古旧的Java集合,并不建议使用。Stack子类所实现的栈功能,也可以通过ArrayDeque来实现。 固定长度的List 数组的工具类Arrays自带一个asList(Object... o)方法,可以将数组或指定数量的对象转换为List,不过需要注意一点: 该类是Arrays类的内部类ArrayList的实例,是固定长度的,相当于数组,只能用于遍历,不能增加和删除里面的元素。 1 public class TestArrayList { 2 3 public static void main(String[] args) { 4 5 List<String> list = Arrays.asList("AA", "BB", "CC"); 6 //显示类的类型为java.util.Arrays$ArrayList 7 System.out.println(list.getClass()); 8 9 list.forEach(System.out::println); 10 //以下会抛出运行时异常java.lang.UnsupportedOperationException 11 list.add("DD"); 12 13 } 14 15 } 线性表的性能选择 一般来说,基于数组的ArrayList在随机访问中性能较好;基于链表的LinkedList在插入、删除中性能较好。但在一般使用中,ArrayList总体性能占优,因此使用非常广泛。 1. 如果需要遍历List元素,ArrayList建议使用随机访问方法;对于LinkedList,建议使用Iterator迭代器 2. 如果需要经常插入、删除大量数据的List集合,可以考虑使用LinkedList

优秀的个人博客,低调大师

Java容器深入浅出之HashSet、TreeSet和EnumSet

Java集合中的Set接口,定义的是一类无顺序的、不可重复的对象集合。如果尝试添加相同的元素,add()方法会返回false,同时添加失败。Set接口包括3个主要的实现类:HashSet、TreeSet和EnumSet。 通过查看Java源码,事实上Java是先实现了Map,然后通过包装一个所有value都为null的集合,形成Set。 HashSet HashSet基于Hash算法实现,因此存取和查找的性能较好。HashSet的主要特点如下: 1. 无顺序的。与添加顺序不同,并且可变。 2. 线程不安全。 3. 集合元素可以是null 4. HashSet是通过元素的HashCode返回值,来确定元素存储位置。 5. 不可重复。HashSet判断元素是否重复的标准是:该元素对象的HashCode()返回值相等,并且equals()方法相等。换句话说,如果两个元素的equals方法相同,但HashCode返回值不相同,HashSet依然可以添加成功。因此,需要注意: 5.1 用Set类保存的元素,尽量保证其equals相等的同时,HashCode返回的值也相等。 5.2 当保存引用类型对象的时候,尽量不要修改其实例变量,否则可能会导致Set集合操作失灵。 1 /* 2 * 测试HashSet的对象添加规则 3 */ 4 class A{ 5 //重写类A的equals方法,恒返回true 6 public boolean equals(Object obj) { 7 return true; 8 } 9 } 10 class B{ 11 //重写类B的HashCode方法,恒返回1 12 public int hashCode() { 13 return 1; 14 } 15 } 16 class C{ 17 //重写类C的HashCode方法,恒返回2 18 public int hashCode() { 19 return 2; 20 } 21 //重写类C的equals方法,恒返回true 22 public boolean equals(Object obj) { 23 return true; 24 } 25 } 26 public class TestHashSet { 27 28 public static void main(String[] args) { 29 30 Set<Object> set = new HashSet<>(); 31 //equals相同,HashCode不相同: 32 //两个对象添加到hash表的不同位置 33 set.add(new A()); 34 set.add(new A()); 35 //HashCode相同, equals不同 36 //此时Hash表会在该HashCode位置,使用链式结构保存这些对象,导致性能下降. 37 set.add(new B()); 38 set.add(new B()); 39 //C类对象只被添加了一次. 40 set.add(new C()); 41 set.add(new C()); 42 43 System.out.println(set); 44 45 } 46 47 } LinkedHashSet LinkedHashSet是HashSet的子类。虽然同样按照元素的HashCode来确定存储位置,但该类同时使用链表来维护添加顺序,也因此,其性能稍低,但是迭代访问元素时优势较大。 TreeSet TreeSet底层采用的是红黑树的数据结构,并且是有序的集合。因此,TreeSet增加了访问第一个、前一个、后一个和最后一个的方法,并且提供了3个截取子树的方法。 TreeSet包括两种排序方法:自然排序和定制排序,默认使用自然排序。 1 public class TestTreeSet { 2 3 public static void main(String[] args) { 4 TreeSet<Integer> nums = new TreeSet<>(); 5 nums.add(5); 6 nums.add(2); 7 nums.add(10); 8 nums.add(-9); 9 //输出,此时已按自然排序 10 System.out.println(nums); 11 System.out.println(nums.first()); 12 System.out.println(nums.last()); 13 //返回<4的子序列 14 System.out.println(nums.headSet(4)); 15 //返回>=5的子序列 16 System.out.println(nums.tailSet(5)); 17 //返回[-3, 4)的子序列 18 System.out.println(nums.subSet(-3, 4)); 19 } 20 21 } TreeSet的自然排序 指的是TreeSet会调用元素的compareTo(Object o)方法来比较元素之间的大小关系,然后将集合按升序排列。 当把一个对象加入TreeSet集合中时,会调用compareTo方法与集合中其它对象比较大小,然后根据红黑树结构定位存储位置。如比较相等,则无法添加。 自然排序中判断两个对象是否相等的唯一标准:两个对象通过compareTo方法返回是否为0。 因此,当重写两个对象的equals方法时,应当重写其compareTo方法,确保有一致的结果。与HashSet类似,当保存引用类型对象的时候,尽量不要修改其实例变量,否则可能会导致操作失效。 TreeSet的定制排序 创建TreeSet集合的对象时,提供一个Comparator对象与该TreeSet集合关联,由该Comparator对象负责元素集合的排序逻辑。 定制排序中判断两个对象是否相等的标准:Comparator对象中比较两个元素是否返回0 class M{ int age; public M(int age) { super(); this.age = age; } @Override public String toString() { return "M [age=" + age + "]"; } } public class TestTreeSetComparator { public static void main(String[] args) { TreeSet<M> ts = new TreeSet<>((o1, o2) -> { M m1 = (M)o1; M m2 = (M)o2; //自定义排序:M对象的age属性越大,对比结果反而越小 return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0; }); ts.add(new M(5)); ts.add(new M(-3)); ts.add(new M(9)); System.out.println(ts); } } EnumSet EnumSet专为枚举类设计,其元素必须是指定枚举类的枚举值,并且不能为null。 EnumSet为有序集合,顺序由枚举值在枚举类中的定义顺序决定。其常用方法如下: 1 enum Season{ 2 SPRING, SUMMER, FALL, WINTER 3 } 4 5 public class TestEnumSet { 6 7 public static void main(String[] args) { 8 //创建一个指定枚举类Season的枚举集合 9 EnumSet<Season> es1 = EnumSet.allOf(Season.class); 10 System.out.println(es1); 11 //创建一个指定枚举类Season的空集合 12 EnumSet<Season> es2 = EnumSet.noneOf(Season.class); 13 System.out.println(es2); 14 //手动添加枚举值 15 es2.add(Season.WINTER); 16 es2.add(Season.SUMMER); 17 System.out.println(es2); 18 //创建一个指定枚举值的枚举集合 19 EnumSet<Season> es3 = EnumSet.of(Season.SPRING, Season.FALL); 20 System.out.println(es3); 21 //创建一个指定枚举值及顺序的枚举集合 22 EnumSet<Season> es4 = EnumSet.range(Season.SUMMER, Season.WINTER); 23 System.out.println(es4); 24 //创建一个es4集合的其余集合es5, 其中es4+es5=es1 25 EnumSet<Season> es5 = EnumSet.complementOf(es4); 26 System.out.println(es5); 27 } 28 } 关于HashSet和TreeSet的选择 作为两个Set接口的典型实现,一般的选择考虑点是: 1. 优先选择HashSet,快速满足日常添加、查询的操作。 2. 有迭代需求时,可以考虑LinkedHashSet 3. 当需要一个排序的Set的时候,再考虑TreeSet 4. 操作枚举类时,优先考虑EnumSet 当需要在多线程环境下使用集合,应该使用Collections工具类在创建集合时就封装为线程安全。 SortedSet set = Collections.synchronizedSortedSet(new TreeSet());

优秀的个人博客,低调大师

Java容器深入浅出之PriorityQueue、ArrayDeque和LinkedList

Queue用于模拟一种FIFO(first in first out)的队列结构。一般来说,典型的队列结构不允许随机访问队列中的元素。队列包含的方法为: 1. 入队 void add(Object o): 指定元素加入队列尾部 boolean offer(Object o):同上,在有限容量队列中,此方法更好 2. 出队 Object poll():获取头部元素,并从队列中删除;如果队列为空,则返回null Object remove():获取头部元素,并从队列中删除; 3. 出队不删除 Object peek():获取头部元素,不删除;如果队列为空,则返回null Object element():获取头部元素,不删除; PriorityQueue PriorityQueue是Queue接口的实现类,但是它并不是一个FIFO的队列实现,具体表现在: 1. 保存顺序与FIFO无关,而是按照元素大小进行重排序;因此poll出来的是按照有小到大来取。 2. 不允许保存null,排序规则有自然排序和定制排序两种,规则与TreeSet一致。 Deque接口与ArrayDeque实现类 Deque实现的是一个双端队列,因此它具有“FIFO队列”及“栈”的方法特性,其中ArrayDeque是其典型的实现类。 1. ArrayDeque的栈实现 1 public class ArrayDequeStack { 2 3 public static void main(String[] args) { 4 ArrayDeque<String> stack = new ArrayDeque<>(); 5 //压栈,此时AAA在最下,CCC在最外 6 stack.push("AAA"); 7 stack.push("BBB"); 8 stack.push("CCC"); 9 System.out.println(stack); 10 //获取最后添加的元素,但不删除 11 System.out.println(stack.peek()); 12 System.out.println(stack); 13 //弹出最后添加的元素 14 System.out.println(stack.pop()); 15 System.out.println(stack); 16 } 17 18 } 2. ArrayDeque的FIFO队列实现 1 public class ArrayDequeQueue { 2 3 public static void main(String[] args) { 4 ArrayDeque<String> queue = new ArrayDeque<>(); 5 //入队 6 queue.offer("AAA"); 7 queue.offer("BBB"); 8 queue.offer("CCC"); 9 System.out.println(queue); 10 //获取但不出队 11 System.out.println(queue.peek()); 12 System.out.println(queue); 13 //出队 14 System.out.println(queue.poll()); 15 System.out.println(queue); 16 } 17 18 } LinkedList实现类 LinkedList比较特殊,它既实现了List接口,同时也实现了Deque接口。因此它具备了List、队列和栈的特性,在应用开发中有广泛的用途。 1 public class TestLinkedList { 2 3 public static void main(String[] args) { 4 LinkedList<String> ll = new LinkedList<>(); 5 //入队 6 ll.offer("AAA"); 7 //压栈 8 ll.push("BBB"); 9 //双端的另一端入队 10 ll.addFirst("NNN"); 11 ll.forEach(str -> System.out.println("遍历中:" + str)); 12 //获取队头 13 System.out.println(ll.peekFirst()); 14 //获取队尾 15 System.out.println(ll.peekLast()); 16 //弹栈 17 System.out.println(ll.pop()); 18 System.out.println(ll); 19 //双端的后端出列 20 System.out.println(ll.pollLast()); 21 System.out.println(ll); 22 } 23 }

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册