Java基础——集结

需要判断服务端请求下来的List与本地保存的List是否相同,则把服务端请求下来的List覆盖本地原先保存的,  数组存储对象特点,stu = new Student,|—|—|—SortedSet(I),则有一下api

后天写项目时遇见七个要求,供给首先次把服务端诉求回来的List保存到地头,后一次跻身,要求决断服务端诉求下来的List与本地保存的List是不是同样,假使一样,则应用本地保存的;假若差别,则把服务端诉求下来的List覆盖本地原先保存的。so,作者不难列了一晃大纲:

  同步调整:焚林而猎四线程并发访谈集结时的线程安全主题素材
    Collections 类中提供了多少个 synchronizedXxx()
方法,该措施可使将钦定集结打包成线程同步的集聚
  List list1 = new ArrayList();//list1不是线程安全的
  List list2 =
Collections.synchronizedList(list1);//list2是线程安全的

6.1排序操作

  • static void reverse(List list)
  • static void shuffle(List list)
  • static void sort(List list)
  • static void sort(List list, Comparator c)
  • static void swaq(List list,int i,int j)
  • static void rotate(List list,int distance)
Arrays,collections(非collection),都以工具类,方法都是静态方法
  • Arrays工具类的点子:
    • sort用于排序数组中的成分
    • toString:用数组中的成分拼接成一个字符串
    • binarySearch:在排序未来的数组中,寻觅某些成分的下标
    • asList:生成二个只读的List,只可以得到无法删增
  • collections工具类的诀要:
    • Swap(list,int,int)调换钦赐list中的八个因素的值
    • Shuffle:随机打乱list成分中的顺序
    • Collections.sort:用于排序list
    • Reverse用于反转list中的成分顺序
    • max,min
    • rotate:移动成分的岗位
    • fill:使用一个值替换list中的全体值
    • frequency推断贰个因素在一个list中冒出的次数
      HashMap是HashSet的底层完毕
      TreeMap是TreeSet的平底完毕
      LinkedHashMap是LinkedHashSet的最底层达成
1、先判别本地中是不是有保留的, 未有则把央求回来的保存的到本地中;

  

4.1 LinkedList

LinkedList同不经常候落实了List和Deque(双向队列)。
Deque接口里面定义了有的能够双向操作队列的章程:

  • addFirst,addLast,offerFirst,offerLast,removeFirst,removeLast,pollFirst,pollLast,getFirst,getLast,peekFirst,peekLast
  • Iterator descendingIterator()//重返以双向队列对应的迭代器
  • Object removeFirstOccurrence(Object o)
  • Object removeLastOccurrence(Object o)

从地方的法子能够看见,LinkedList不仅能够当双向队列使用,还可当栈使用。

set接口

  • set分支的特征是:未有种种,不能再一次
  • set的api大约都以承袭collection,未有和煦的
1、最粗暴的法子
package com.example;import java.util.ArrayList;public class CheckDiffList { public static void main(String[] args) { List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { list1.add("test" + i); list2.add("test" + i * 2); } System.out.println(getDiffrent(list1, list2));// 判断两个List内的元素是否相同// getDiffrent total times 2514359// false } /** * 判断两个List内的元素是否相同 * * @param list1 * @param list2 * @return */ private static boolean getDiffrent(List<String> list1, List<String> list2) { long st = System.nanoTime(); if (list1.size() != list2.size { System.out.println("getDiffrent total times " + (System.nanoTime; return false; } for (String str : list1) { if (!list2.contains { System.out.println("getDiffrent total times " + (System.nanoTime; return false; } } System.out.println("getDiffrent total times " + (System.nanoTime; return true; }}

这种艺术相当于自己最先想到的,总共要循环的次数是八个List的size的乘积,从出口看耗费时间也是相比长的。

    1.冬天性 != 随机性,是指成分在底层存款和储蓄的职责是冬季的
    2.不行重复性 当想Set中增添进一样的要素时,后边的丰富不进来
    注:不可重复性中一样种性其他论断,依照加多进Set中的成分所在类中的equals()和hashCode()方法,所以不容置疑要重写equals()和hashCode()方法。

5.1 HashMap和HashTable实现类

HashTable是八个古老的兑现类,然则是线程安全的。

和HashSet类似的是,若是接纳可变对象作为HashMap和HashTable的Key,且前后相继修改了key的话,那么,程序将再也无力回天精确访谈到Map中被修改过Key

HashMap也会有贰个子类,叫LinkedHashMap,使用双向链表来爱抚key-value的主次。
Properites是HashTable的子类,该对象在拍卖属性文件的时候特意方便。包罗如下接口:
String getProperty(String key)
String getProperty(String key, String defaultValue)
Object setProperty(String key,String value)
void load(InputStream inStream)//加载属性文件
void store(OutputStream,String comment)//写入属性文件

Collection接口

因为Collection是贰个接口,所以无法被实例化。则有瞬间api

  • 增:add和addAll
  • 删:remove,removeAll (删除交集),clear(清空集结)
  • 改:Collection未有改的方式(List分支才有)
  • 查:
  • contains:决断集结中是或不是带有某些成分
  • containsAll:用于决断叁个聚众是还是不是完全包蕴另外三个成团
  • isEmpty:推断一个凑合是或不是为空
  • retainAll:总结交集
  • size:计算集合中的元素
  • toArray:把三个聚众转变为数组,数组霜月素的逐一与聚焦一致
  • 迭代器
    • Iterator用于获取迭代器,迭代器是为着叁个叁个按顺序收取成分
    • 迭代:为了获取第n个因素,必需先获得前n – 1个要素
    • 迭代器Iterator有贰个hasNext方法,用于推断是或不是还会有下一项
2、利用Java中为List提供的议程retainAll()
package com.example;import java.util.ArrayList;import java.util.List;public class CheckDiffList { public static void main(String[] args) { List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { list1.add("test" + i); list2.add("test" + i * 2); } System.out.println(getDiffrent2(list1, list2));// 判断两个List内的元素是否相同// getDiffrent2 total times 7563// false } /** * 判断两个List内的元素是否相同 * <p> * 此方法有bug 见Food.class * * @param list1 * @param list2 * @return */ private static boolean getDiffrent2(List<String> list1, List<String> list2) { long st = System.nanoTime(); System.out.println("getDiffrent2 total times " + (System.nanoTime; return !list1.retainAll; }}

很显然,方法2比办法1耗费时间少比非常多。大家能够来拜会retainAll()的源码

 /** * Retains only the elements in this list that are contained in the * specified collection. In other words, removes from this list all * of its elements that are not contained in the specified collection. * * @param c collection containing elements to be retained in this list * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull; //调用自己的私有方法 return batchRemove; } //如果此 collection 由于调用而发生更改,则返回 true //集合A比较与集合B的交集 private boolean batchRemove(Collection<?> c, boolean complement) { //获得当前对象的所有元素 final Object[] elementData = this.elementData; //w:标记两个集合公共元素的个数 int r = 0, w = 0; //设置标志位 boolean modified = false; try { //遍历集合A for (; r < size; r++) //判断集合B中是否包含集合A中的当前元素 if (c.contains(elementData[r]) == complement) //如果包含则直接保存。 elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. // 如果 c.contains() 抛出异常 if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); //w为当前集合A的length w += size - r; } //如果集合A的大小放生改变 if (w != size) { // clear to let GC do its work // 清除工作 for (int i = w; i < size; i++) elementData[i] = null; //记录集合中元素的改变(add/remove) modCount += size - w; //设置当前数组的大小 size = w; //返回为true modified = true; } } return modified; }

哈哈,源码我看得亦非特意懂,里边有关联到重大字transient,还恐怕有List的contains()、System.arraycopy(Object
src, int srcPos,Object dest, int destPos, int length)方法。

唯独结论是retainAll方法的重返值:假诺会集A数组的高低没有改观,则赶回false。假使集合A和集合B是一模一样的聚合,也会回去false。八个汇聚未有交集,才会回到true。一句话来讲,判定五个汇聚是还是不是有混合,有则赶回false,无则赶回true。

还大概有为何,小编的笺注上此情势用来决断多个List是不是一样有bug,并非说java那些法子有bug,而是大家一直运用来去判别多个list成分是还是不是一律有bug,是由于List的contains()的主意导致的,那个demo中是List<String>,假设是List<Person>就拜看到差异了。

List的contains()中调用的是object的equals方法,而String复写了Object的equals。那个自家想另起一文来单独记录。哈哈哈,前后花了一些个小时才搞明白,只可以怪本身本领太菜。

  4.2因素查询的操作:
    Object get(Object key)
    boolean containsKey(Object key)
    boolean containsValue(Object value)
    int size()
    boolean isEmpty()
    boolean equals(Object obj)

3.2 ArrayList和Vector实现类

双面都以依照数组实现的List类,封装了七个动态再分配的Object[]数组,各类对象有几个capacity属性,那么些个性平日无须关切,可是要是要贰遍多量的插入成分,能够透过ensureCapacity(int)来二回性的充实capacity,进而减少重分配次数。
capacity属性默许为10,可以由此如下多少个方法来操作:

  • void ensureCapacity(int minCapacity)
  • void trimToSize() //调节集结的capacity为当前列表大小

Vector是一个古老的集合,里面比较多种复的措施,并且名字十分短,所以平日不推荐使用。

Vector有贰个Stack子类,有peek,pop和push方法,模拟栈这种数据结构。

有好几索要专注的是,Vector是线程安全的,但ArrayList是不安全的,可是也照例能够经过Collections工具类来让其变得线程安全

HashSet(重点)
  • HashSet的特点:增加和删除,查询 功效都极高,瑕玷,占用空间专门大
  • java中每贰个对象都有二个“哈希码”(能够相比较,每一个目的都有一个“对象互斥锁”),那几个哈希码能够通过hashCode来获得,其实哈希码就是叁个平头
  • 系统内置的类的靶子,倘若剧情一律,哈希码就一样,内容不一样,哈希码不料定分裂
  • 自定义的类,假如剧情一律,哈希码也是不一致的
    • 系统内置的类,都重写过hasjCode方法!保证哈希码就是基于内容计算出来的!而大家自定义的类,直接访问的就是Object的hashCode方法!Object的hashCode仅仅是大致的回来内部存款和储蓄器地址,
  • 为了确定保证自定义的类,三个指标内容一样的前提下,哈希码也一直以来,则须要我们通力合作重写Object的hashSet方法!
  • 对象的哈希码是用来散列的,所谓散列正是依照不相同的哈希码,把指标分配到分裂的HashSet的区域(术语上叫桶)中
  • 哈希码一样的八个对象,会进来同贰个区域中,独有同一个区域中的对象,才进行相比,其余区域的靶子并不是相比,因为哈希码是基于目的的内容产生的,哈希码分化,内容自然分裂
  • 又因为哈希码同样,对象的剧情不一定就同一。所以哈希码一样的前提下,还要更进一竿比较,相比时会回调equals方法。Object的equals是相比较地址

简书菜鸟,第4回写博客,一是为着加固一下,加深影像,二是留作多个书稿,方便现在翻看。还应该有吗,正是希望在此地能获取大神得指引,避防误人子弟。如有不足,敬请谅解,应接指正,多谢!

  4.3元视图操作的办法:
    Set keySet()
    Collection values()
    Set entrySet//遍历Key集

5.2 SortedMap接口和TreeMap实现类

和TreeSet同样,TreeMap也是选择红黑树对TreeMap的全数key进行排序,进而使具有的key-value属于有序状态。
也是提供了三种排序情势:

  • 当然排序:key必得贯彻Comparable接口
  • 定制排序:传入Comparator对象
    就像剖断八个成分相等的科班,TreeSet中判别八个key相等的正儿八经也是四个key通过equals重临true,通过compareTo重回0

落到实处的法子参照他事他说加以考察TreeSet的法子,有:firstEntry,firstKey,lastEntry,lastKey,higher,lower,subMap,headMap,tailMap

Map接口

  • Map分支的表征:存放键值对。存放键值—>值得炫彩关系。个中,键值无法重复,未有各种,值能够另行,
  • Map的api:
    • 增:put,putAll
    • 删:
      • remove(Object key),依照键值删除全数键值对
        map的remove方法,重临的是此次删除的值!若无删着,则赶回null!
        Collection的remove方法重回的是Boolean类型,true表示删除着了,false则从未
      • clear
  • 改:假如键值重复,则是覆盖效果(修改)
  • 查:
    • containsKey:推断map中是或不是带有有些键值
    • containsValue:推断map中是不是包蕴有个别值
    • get(Objetc key):传入键值,重临值,键值不设有,重回null
    • getOrDefault(Object key,Object Default)
    • isEmpty
    • size():键值对的对数
    • keySet:keySet用于获取map中全数 键的集聚
    • values:values用于获取map中全数值的集中
    • entrySet: entrySet用于获取键值对的聚众
2、有则决断央浼回来的与本土中List个数是或不是等于 若不等于,则把央求回来的隐讳原先在该地中保存的;

  排序操作:(均为static方法)
    reverse(List):反转 List 相月素的次第
    shuffle(List):对 List 集结成分举行随机排序
    sort(List):依照成分的本来顺序对点名 List 集合元素按升序排序
    sort(List,Comparator):依据钦点的 Comparator 产生的相继对 List
会集成分举行排序
    swap(List,int, int):将点名 list 会集中的 i 处成分和 j
处元素进行置换
  检索和替换
    Object
max(Collection):依据元素的自然顺序,再次回到给定集结中的最大意素
    Object max(Collection,Comparator):遵照 Comparator
内定的次第,重临给定集结中的最概略素
    Object min(Collection)
    Object min(Collection,Comparator)
    int
frequency(Collection,Object):再次来到钦定集结中钦定成分的产出次数
    void copy(List dest,List src):将src中的内容复制到dest中
    boolean replaceAll(List list,Object oldVal,Object
newVal):使用新值替换 List 对象的有所旧值

1. Java会集概述

Java会集主要由多个接口派生而出,Collection和Map
|—Collection(I)
|—|—Set(I)
|—|—|—EnumSet(C)
|—|—|—SortedSet(I)
|—|—|—|—TreeSet(C)
|—|—|—HashSet(C)
|—|—|—|—LinkedHashSet(C)
|—|—Queue(I)
|—|—|—PriorityQueue(C)
|—|—|—Deque(I) |
|——————-|—LinkedList(C)
|—|—List(I)——|
|—|—|—ArrayList(C)
|—|—|—Vector(C)
|—|—|—|—Stack(C)

|—Map
金沙澳门官网7817网址,|—|—EnumMap
|—|—IdentityHashMap
|—|—HashMap(C)
|—|—|—LinkedHashMap
|—|—HashTable(C)
|—|—|—Properites
|—|—SortedMap(I)
|—|—|—TreeMap(C)
|—|—WeakHashMap

Collection提供了如下接口:

  • add,addAll,contains,containsAll,remove,removeAll,retainAll
  • clear,isEmpty,size,toArray,iterator

遍历能够透过iterator迭代器来张开,也得以因而foreach来拓宽。
Iterator接口里面定义了以下多少个主意:

  • boolean hasNext()
  • Object next()
  • void remove()
LinkedList
  • 特点:查询效能低,增加和删除成效高,因为LinkedList底层是用链表完成的!链表在内部存款和储蓄器中的存放特点是“不总是存放”,正因为不一连,所以查询效能低,增加和删除作用高
  • LinkedList的都有主意:
  • addFirst ,
  • addLast ,
  • removeFirst ,
  • removeLast
3、若相等,遍历诉求下来List与本土中保存的List各种要素是还是不是同样 若不雷同,则把央浼回来的掩没原先在该地中保存的;

操作集结的工具类:Collections
  区别于Collection

3.1 List接口和ListInterator接口

List除了能够选取Collection接口的整个主意之外,还有一点点得以依照索引来操作集结成分的办法:

  • void add(int index, Object element)
  • boolean addAll(int index, Collection c)
  • Object get(int index)
  • int indexOf(Object o)
  • int lastIndexOf(Object o)
  • Object remove(int index)
  • Object set(int index,Object element)
  • List subList(int fromIndex,int toIndex)

List决断相等的标准,也是通过equals方法重返true就能够

List还提供了八个listIterator()方法,该方法重回三个ListIterator对象,除了Iterator有的方式之外,还富含:

  • boolean hasPrevious()
  • Object previous()
  • void add()

集中框架的三翻五次种类

  • . Collection
    • List
      • ArrayList
      • LinkedList
      • Vector
        • Stack
    • Set
      • HashSet
      • TreeSet
      • LinkesHashSet
  • Map
    • HashMap
    • TreeMap
    • LinkedHashMap
    • Hashtable
      如上加粗的类名就是接口,Collection和Map是聚众框架中的父接口
4、方法3的立异版(首先去剖断list1、list2的size大小)
package com.example;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class CheckDiffList { public static void main(String[] args) { List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { list1.add("test" + i); list2.add("test" + i * 2); } System.out.println(getDiffrent4(list1, list2));// 判断两个List内的元素是否相同// getDiffrent4 total times 37313357// false } /** * 判断两个List内的元素是否相同 * * @param list1 * @param list2 * @return */ private static boolean getDiffrent4(List<String> list1, List<String> list2) { long st = System.nanoTime(); Map<String, Integer> map = new HashMap<String, Integer>(list1.size() + list2.size; List<String> maxList = list1; List<String> minList = list2; if (list2.size() > list1.size { maxList = list2; minList = list1; } for (String string : maxList) { map.put(string, 1); } for (String string : minList) { Integer cc = map.get; if (cc != null) { map.put(string, ++cc); continue; } return false; } System.out.println("getDiffrent4 total times " + (System.nanoTime; return true; }}

主意4对七个list的分寸举办了判别,小的在最终增添,那样会减小循环里的剖断,品质又有了必然的晋升!
但本例中艺术4比办法3耗费时间还要长,小编的掌握是多做了壹遍判定五个群集size大小的剖断,不过自身感觉这么些本性能够就义。

办法3和办法4都有伙同的三个标题:借使某些list中有再度成分的话,由于map不允许有一致的key,所以艺术失效!

相比以上4种艺术,耗费时间排名getDiffrent2<getDiffrent1<getDiffrent3<getDiffrent4,方法4比办法3多了三次判别,更耗费时间我得以理解,为何3和4比1还耗费时间呢?

写的写的友善都写懵逼了,第一回写博客,原来是想追究一下那4种方法的习性,结果成了提供了推断多少个list是还是不是同样的4种艺术,接待各位大神指正,呵呵哒。

以下是总体的代码(注意这几个类最棒永不全部运营,因为方法2会退换list内的原委,提出分别运营1、2、3、4措施)

package com.example;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class CheckDiffList { public static void main(String[] args) { List<String> list1 = new ArrayList<String>(); List<String> list2 = new ArrayList<String>(); for (int i = 0; i < 10000; i++) { list1.add("test" + i); list2.add("test" + i * 2); } System.out.println(getDiffrent(list1, list2)); System.out.println(getDiffrent2(list1, list2)); System.out.println(getDiffrent3(list1, list2)); System.out.println(getDiffrent4(list1, list2));// 判断两个List内的元素是否相同// getDiffrent total times 2514359 // false// getDiffrent2 total times 7563 // false// getDiffrent3 total times 26976244 // false// getDiffrent4 total times 37313357 // false } /** * 判断两个List内的元素是否相同 * * @param list1 * @param list2 * @return */ private static boolean getDiffrent4(List<String> list1, List<String> list2) { long st = System.nanoTime(); Map<String, Integer> map = new HashMap<String, Integer>(list1.size() + list2.size; List<String> maxList = list1; List<String> minList = list2; if (list2.size() > list1.size { maxList = list2; minList = list1; } for (String string : maxList) { map.put(string, 1); } for (String string : minList) { Integer cc = map.get; if (cc != null) { map.put(string, ++cc); continue; } System.out.println("getDiffrent4 total times " + (System.nanoTime; return false; } System.out.println("getDiffrent4 total times " + (System.nanoTime; return true; } /** * 判断两个List内的元素是否相同 * * @param list1 * @param list2 * @return */ private static boolean getDiffrent3(List<String> list1, List<String> list2) { long st = System.nanoTime(); Map<String, Integer> map = new HashMap<String, Integer>(list1.size() + list2.size; for (String string : list1) { map.put(string, 1); } for (String string : list2) { Integer cc = map.get; if (cc != null) { map.put(string, ++cc); continue; } System.out.println("getDiffrent3 total times " + (System.nanoTime; return false; } System.out.println("getDiffrent3 total times " + (System.nanoTime; return true; } /** * 判断两个List内的元素是否相同 * <p> * 此方法有bug 见Food.class * * @param list1 * @param list2 * @return */ private static boolean getDiffrent2(List<String> list1, List<String> list2) { long st = System.nanoTime(); System.out.println("getDiffrent2 total times " + (System.nanoTime; return !list1.retainAll; } /** * 判断两个List内的元素是否相同 * * @param list1 * @param list2 * @return */ private static boolean getDiffrent(List<String> list1, List<String> list2) { long st = System.nanoTime(); if (list1.size() != list2.size { System.out.println("getDiffrent total times " + (System.nanoTime; return false; } for (String str : list1) { if (!list2.contains { System.out.println("getDiffrent total times " + (System.nanoTime; return false; } } System.out.println("getDiffrent total times " + (System.nanoTime; return true; }}

正文参照他事他说加以考察

List list1 = new ArrayList();
list1.add(123);
list1.add(332);
list1.add(2332);
//list1向list2复制
List list2 = new ArrayList();//错误的方式,因为此时list2的长度为0
List list2 = ArrayList.asList(new Object[list1.size()]);
Collections.copy(list2, list1);

5 Map接口

Map用于保存具有映射关系的数据。Map接口中定义了之类常用方法:

  • void clear()
  • boolean containsKey(Object key)
  • boolean containsValue(Object value)
  • Set entrySet()
  • Object get(Object key)
  • boolean isEmpty()
  • Set keySet()
  • Object push(Object key, Object value)
  • void putAll(map m)
  • Object remove(Object key)
  • int size()
  • Collection values()
    Map中富含多少个中间类:Entry,包括getKey,getValue,setValue多个艺术

List接口

  • List分支的性状是:有各种,能重新
  • List的api:
    • add(int,Object):在钦命地点添法郎素
    • addAll(int,Collection)
    • remove(int):按下标删除成分
    • removeAll
    • set(int,Object):把某部地点上的因素替换来某些值
    • get():遵照下标率性拜谒成分
      (List能够使用迭代器访谈,因为她继续了Collection,也就一而再了Collection的interator方法来获得迭代器)
    • indexOf() 和 lastIndextOf()
    • listIterator:获取贰个双向迭代器
    • subList