Arrays与Java集合类

2018-04-12  本文已影响0人  ThreeGold

Arrays

Arrays是一个工具类,用于操作数组的,里面定义了常见操作数组的静态方法。

常见的方法有:排序,二分查找,将数值变成字符串,下面通过代码讲解:


public class ArraysTest {

    public static void main(String[] args) {

    int[] arr = { 4, 1, 5, 8, 2, 9 };

    System.out.println(Arrays.toString(arr));// 输出 原始数组 [4, 1, 5, 8, 2, 9]

    // 对arr进行排序,默认是从小到大。

    Arrays.sort(arr);

    System.out.println(Arrays.toString(arr));// 输出 排序[1, 2, 4, 5, 8, 9]


    // 二分查找

    // 如果没有找到,返回 插入点index=-5,负号说明没有找到

    // -5说明 要找的7本应该在5-1=4的下标,即现在8的位置

    int index = Arrays.binarySearch(arr, 7);

    System.out.println("index = " + index);// index = -5


    // 用8来填充整个数组

    Arrays.fill(arr, 8);

    System.out.println(Arrays.toString(arr));// [8, 8, 8, 8, 8, 8]


    // 将数组变成集合,如果数组中存储的是基本数据类型的元素,

    //那么会将该数组作为集合的元素存在。

    List<int[]> list = Arrays.asList(arr);

    System.out.println(list);// [[I@41975e01]



    //如果数组中存储的是引用数据类型的元素,那么变成集合时,

    //这些元素会作为集合的元素存在。

    Integer[] arr02 = { 4, 1, 5, 8, 2, 9 };

    List<Integer> list02 = Arrays.asList(arr02);

    System.out.println(list02);// [4, 1, 5, 8, 2, 9]


    //数组变成集合后,不可以使用增删等改变数组长度的方法。

    // list02.add(12);// throw "java.lang.UnsupportedOperationException"


    // 复制数组copyOf(复制源,新数组长度)

    Integer[] arr3 = Arrays.copyOf(arr02, arr02.length + 1);

    System.out.println(Arrays.toString(arr3)); //[4, 1, 5, 8, 2, 9, null]

    }

}

Java集合类

java的集合类主要由2个接口派生而出:CollectionMap

Collection和Map是Java集合框架的根接口,这2个接口又包含了一些接口或实现类。

Connection.png map.png

上图所有的集合类,都实现了Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法。它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。也就是说如果是先Iterator接口,那么在遍历集合中元素的时候,只能往后遍历,被遍历后的元素不会在遍历到,通常无序集合实现的都是这个接口,比如HashSet,HashMap;而那些元素有序的集合,实现的一般都是LinkedIterator接口,实现这个接口的集合可以双向遍历,既可以通过next()访问下一个元素,又可以通过previous()访问前一个元素,比如ArrayList。


Collection

List

List是一个接口,List里面常用的方法有:

  1. add(object) 在集合末尾添加一个元素

  2. size() 获取list集合的大小

  3. remove(index)移除指定索引位置的元素,并返回这个元素

  4. remove(object)移除指定的对象,返回值是boolean类型

  5. removeAll(Collection)按照指定的数据来删除

  6. add(index,object) 在指定位置添加一个元素

  7. get(index) 获取指定位置的元素

  8. toString()方法来自于Object

  9. toArray() 返回一个数组

  10. isEmpty() 判断集合是否为空

  11. clear() 清空集合

  12. contains() 判断集合中是否包含某个对象

  13. addAll(Collection) 在集合末尾添加另一个集合

  14. addAll(index,Collection) 在指定位置末尾添加另一个集合

下面通过一段代码来说明上面的方法:


public class ListTest {

    public static void main(String[] args) {

    // 创建一个ArrayList对象,List里面存的全是对象

    List list = new ArrayList();

    list.add("哈哈");

    list.add(1);

    list.add(10);

    list.add("ss");

    list.add("aa");

    list.add("3");

    System.out.println("移除前:" + list);// 移除前:[哈哈, 1, 10, ss, aa, 3]

    System.out.println(list.size());// 6


    String removed = (String) list.remove(0);// 移除第0个元素

    System.out.println("移除的是:" + removed);// 移除的是:哈哈

    System.out.println("移除后:" + list);// 移除后:[1, 10, ss, aa, 3]

    System.out.println(list.size());// 5


    // 移除掉 10这个元素

    // list.remove(1);或者下面的方法

    list.remove(Integer.valueOf(10));

    System.out.println(list.size());// 4


    System.out.println("list第0个元素是:" + list.get(0));// list第0个元素是:1


    Object[] array = list.toArray();

    System.out.println(Arrays.toString(array));// [1, ss, aa, 3]

    System.out.println("数组的长度=" + array.length);// 数组的长度=4


    // list包含1这个元素吗?true

    System.out.println("list包含1这个元素吗?" + list.contains(1));


    List list02 = new ArrayList<>();

    list02.add("new");

    list02.add("new");

    list.addAll(list02);//添加一个集合

    System.out.println(list);// [1, ss, aa, 3, new, new]


    List list03 = new ArrayList<>();

    list03.add("A");

    list03.add("ss");

    list03.add("new");

    list.removeAll(list03);//移除集合和集合相交的部分

    System.out.println(list);//[1, aa, 3] 只移除有的ss和new,A不管。有new则会把原数据的new全移除


    System.out.println("list为空吗?" + list.isEmpty());// list为空吗?false


    list.clear();// 清空集合

    System.out.println("list为空吗?" + list.isEmpty());// list为空吗?true

    }

}

上面的代码已经包含了list常用的一些方法,读懂代码就能理解怎么使用这些方法了。


ArrayList

ArrayList是List接口的一个实现类,ArrayList是基于数组实现的,传说中的动态数组,里面封装了一个数组,数组有一个默认长度10。

ArrayList怎么实现动态长度的呢?
调用add()的时候,首先会进行判断,如果数组装满了,就创建一个长度更大的数组(长度为之前数组长度的1.5倍),然后把之前数组的元素copy到行数组,再把要添加的那个元素加入新数值。

ArrayList方法大多为List方法,ArrayList转换为数组的方法:


ArrayList al = new ArrayList<>();

al.add("abc1");

al.add("abc2");

al.add("3");

//必须ArrayList里面全部放的String类型才能这样转

String[] arr = (String[]) al.toArray(new String[al.size()]);

System.out.println(Arrays.toString(arr));//[abc1, abc2, 3]

把上面第4行的al.add("3");变成al.add(3); String[] arr = (String[]) al.toArray(new String[al.size()]);这行代码运行就会报错,必须改为Object[] arr = al.toArray(new Object[al.size()]);才能正确。


Vector(向量类)

Vector和ArrayList类似,区别在于Vector是同步类,因此开销比ArrayList要大。我们通过代码来了解这个类:

public class VectorTest {

    public static void main(String[] args) {

    Vector vector = new Vector<>();

    vector.addElement("1234"); // 没有返回值

    vector.add("string"); // 返回true

    vector.addElement(2);

    vector.add(1);

    System.out.println(vector);// [1234, string, 2, 1]


    // vector.setElementAt(obj, index)

    vector.setElementAt(3, 2);// 没有返回值

    System.out.println(vector);// [1234, string, 3, 1]


    // vector.set(index, element)

    Object oldValue = vector.set(2, 99);// return oldValue

    System.out.println(oldValue); // 3

    System.out.println(vector);// [1234, string, 99, 1]


    vector.insertElementAt("55", 1);// 在index位置插入某个值,没有返回值

    System.out.println(vector);// [1234, 55, string, 99, 1]


    Object oldValue2 = vector.remove(0);// 删除指定位置的值,return oldValue

    System.out.println(oldValue2);// 1234

    System.out.println(vector);// [55, string, 99, 1]


    vector.removeElementAt(0);// 删除指定位置的值,没有返回值

    System.out.println(vector);// [string, 99, 1]

    vector.remove(new Integer(99));// remove方法中源码直接调用 return removeElement(o);

    System.out.println(vector);// [string, 1]


    vector.removeElement("string");// 删除某个值,return true

    System.out.println(vector);// [1]


    vector.removeAllElements();// 没有返回值

    System.out.println(vector);// []


    vector.addElement("1");

    vector.add("2");

    vector.addElement(3);

    vector.add(4);

    System.out.println(vector);//[1, 2, 3, 4]

    /**
    * (1)indexOf(Object obj)
    * 从向量头开始搜索obj,返回所遇到的第一个obj对应的下标,若不存在此obj,返
    * 回-1.
    * (2)indexOf(Object obj,int index)
    * 从index所表示的下标处开始搜索obj.
    * (3)=lastindexOf(Object obj)
    * 从向量尾部开始逆向搜索obj.
    * (4)lastIndex(Objectobj,int index)
    * 从index所表示的下标处由尾至头逆向搜索obj.
    * (5)firstElement()
    * 获取向量对象中的首个obj
    *(6)lastElement()
    * 获取向量对象的最后一个obj
    */

    System.out.println(vector.firstElement());// 1

    System.out.println(vector.lastElement());// 4


    // 2种迭代输出

    // elements()此方法将向量对象对应到一个枚举类型。

    Enumeration elements = vector.elements();
    while (elements.hasMoreElements()) {// hasMoreElement() 来判断集合中是否还有    其他元素。
        System.out.print(elements.nextElement());//1234 // nextElement() 来获取下一个元素
    }

    Iterator iterator = vector.iterator();
    while (iterator.hasNext()) {
        System.out.print(iterator.next());//1234
    }

    }

}

以上就是Vector的全部用法,读懂了代码就能正确使用向量类了。下面我们来谈Enumeration和Iterator的区别。


Iterator接口中定义了三个方法:

1.hasNext()
是否还有下一个元素.

2.next()
返回下一个元素.

3.remove()
删除当前元素.

Enumeratio接口中定义了两个方法:

1.boolean hasMoreElements()
是否还有下一个元素.

2.Object nextElement()
返回下一个元素.

比较:
1.Enumeration 枚举接口其实是一个比 Iterator 迭代器接口更早期的枚举集合中的元素的接口。

2.Enumeration 虽然可能过时而被 Iterator 替代,但很多 servlet 还用到,所以还有学习的必要。

3.迭代器允许调用方利用定义良好的语义在迭代期间从迭代器所指向的集合移除元素。

4.方法名称得到了改进。

这里要注意几点:

  1. Iterator是用来替代Enumeration的,Enumeration中只定义了两个方法,不具备删除功能.

  2. 调用next()方法后才可以调用remove()方法,而且每次调用next()后最多只能调用一次remove()方法,否则抛出IllegalStateException异常.


LinkedList

LinkedList其实也就是我们在数据结构中的链表,这种数据结构有以下特征:

下面来说说常用的一些方法:

add

下面是代码演示:

LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("first");
linkedList.add("second");
linkedList.add("third");
System.out.println(linkedList);

linkedList.addFirst("addFirst");
System.out.println(linkedList);

linkedList.addLast("addLast");
System.out.println(linkedList);

linkedList.add(2, "addByIndex");
System.out.println(linkedList);

输出为:

[first, second, third]
[addFirst, first, second, third]
[addFirst, first, second, third, addLast]
[addFirst, first, addByIndex, second, third, addLast]

remove

下面是代码演示

LinkedList<String> linkedList02 = new LinkedList<>();
linkedList02.add("first");
linkedList02.add("second");
linkedList02.add("second");
linkedList02.add("third");
linkedList02.add("four");
linkedList02.add("five");
System.out.println(linkedList02);

linkedList02.remove();
System.out.println("remove: " + linkedList02);

linkedList02.remove("second");
System.out.println("remove(Object): " + linkedList02);

linkedList02.remove("six");
System.out.println("remove(Object) not exist: " + linkedList02);

linkedList02.remove(2);
System.out.println("remove(index): " + linkedList02);

linkedList02.removeFirst();
System.out.println("removeFirst: " + linkedList02);

linkedList02.removeLast();
System.out.println("removeLast:" + linkedList02);

System.out.println("----------------------------------");

linkedList02.clear();
linkedList02.add("first");
linkedList02.add("second");
linkedList02.add("first");
linkedList02.add("third");
linkedList02.add("first");
linkedList02.add("five");
System.out.println(linkedList02);

linkedList02.removeFirstOccurrence("first");
System.out.println("removeFirstOccurrence: " + linkedList02);

linkedList02.removeLastOccurrence("first");
System.out.println("removeLastOccurrence: " + linkedList02);

输出为:

[first, second, second, third, four, five]
remove: [second, second, third, four, five]
remove(Object): [second, third, four, five]
remove(Object) not exist: [second, third, four, five]
remove(index): [second, third, five]
removeFirst: [third, five]
removeLast:[third]
----------------------------------
[first, second, first, third, first, five]
removeFirstOccurrence: [second, first, third, first, five]
removeLastOccurrence: [second, first, third, five]

get

下面是代码演示:

LinkedList<String> linkedList03 = new LinkedList<>();
linkedList03.add("first");
linkedList03.add("second");
linkedList03.add("second");
linkedList03.add("third");
linkedList03.add("four");
linkedList03.add("five");
System.out.println(linkedList03);

linkedList03.get(3);
System.out.println("get(3): " + linkedList03.get(3));

linkedList03.getFirst();
System.out.println("getFirst: " + linkedList03.getFirst());

linkedList03.getLast();
System.out.println("getLast: " + linkedList03.getLast());

System.out.println(linkedList03);

输出为:

[first, second, second, third, four, five]
get(3): third
getFirst: first
getLast: five
[first, second, second, third, four, five]

注意到了,链表前后没有产生变化。

push、pop、poll

下面是代码演示:

LinkedList<String> linkedList04 = new LinkedList<>();
linkedList04.push("first");
linkedList04.push("second");
linkedList04.push("second");
linkedList04.push("third");
linkedList04.push("four");
linkedList04.push("five");
System.out.println("linkedList: " + linkedList04);
System.out.println("pop: " + linkedList04.pop());
System.out.println("after pop: " + linkedList04);
System.out.println("poll: " + linkedList04.poll());
System.out.println("after poll: " + linkedList04);

输出为:

linkedList: [five, four, third, second, second, first]
pop: five
after pop: [four, third, second, second, first]
poll: four
after poll: [third, second, second, first]

通过代码示例可以看出:push,pop的操作已经很接近stack的操作了。

如果链表为空的时候,看看poll与pop是啥区别:

LinkedList<String> linkedList05 = new LinkedList<>();
System.out.println("poll: " + linkedList05.poll());//null
//下面代码会报java.util.NoSuchElementException异常
// System.out.println("pop: " + linkedList05.pop());

可以看出poll返回null,而pop则产生异常。

peek

E peek():获取第一个元素,但是不移除;

E peekFirst():获取第一个元素,但是不移除;

E peekLast():获取最后一个元素,但是不移除;

下面是代码演示:

LinkedList<String> linkedList06 = new LinkedList<>();
linkedList06.push("first");
linkedList06.push("second");
linkedList06.push("second");
linkedList06.push("third");
linkedList06.push("four");
linkedList06.push("five");
System.out.println("linkedList: " + linkedList06);
System.out.println("peek: " + linkedList06.peek());
System.out.println("peekFirst: " + linkedList06.peekFirst());
System.out.println("peekLast: " + linkedList06.peekLast());
System.out.println("linkedList: " + linkedList06);

输出为:

linkedList: [five, four, third, second, second, first]
peek: five
peekFirst: five
peekLast: first
linkedList: [five, four, third, second, second, first]

如果没找到对应的元素,则统统输出null,比如空的LinkedList。

offer

下面是代码演示:

LinkedList<String> linkedList07 = new LinkedList<>();
linkedList07.push("first");
linkedList07.push("second");
linkedList07.push("third");
System.out.println("linkedList: " + linkedList07);

linkedList07.offer("four");
System.out.println("linkedList: " + linkedList07);

linkedList07.offerFirst("zero");
System.out.println("linkedList: " + linkedList07);

linkedList07.offerLast("five");
System.out.println("linkedList: " + linkedList07);

输出为:

linkedList: [third, second, first]
linkedList: [third, second, first, four]
linkedList: [zero, third, second, first, four]
linkedList: [zero, third, second, first, four, five]

其他

LinkedList中常用的方法基本都列出来了,当然还有一些其他的例子,

这里就一起演示了:

LinkedList<String> linkedList08 = new LinkedList<>();
linkedList08.push("first");
linkedList08.push("second");
linkedList08.push("second");
linkedList08.push("third");
linkedList08.push("four");
linkedList08.push("five");
System.out.println("linkedList: " + linkedList08);

System.out.println("linkedList.contains(\"second\"): "+ linkedList08.contains("second"));
System.out.println("linkedList.contains(\"six\"): "+ linkedList08.contains("six"));

System.out.println("linkedList.element(): "+ linkedList08.element());

System.out.println("linkedList: " + linkedList08);

System.out.println("linkedList.set(3, \"set\"): "+ linkedList08.set(3, "set"));
System.out.println("linkedList: " + linkedList08);

//截取list,和String.substring类似
System.out.println("linkedList.subList(2,4): "+ linkedList08.subList(2, 4));

System.out.println("linkedList: " + linkedList08);

输出为:

linkedList: [five, four, third, second, second, first]
linkedList.contains("second"): true
linkedList.contains("six"): false
linkedList.element(): five
linkedList: [five, four, third, second, second, first]
linkedList.set(3, "set"): second
linkedList: [five, four, third, set, second, first]
linkedList.subList(2,4): [third, set]
linkedList: [five, four, third, set, second, first]

从输出可以看出,除了set改变原linkedlist,其他几个方法都不改变原链表。

LinkedList用法转载于: https://blog.csdn.net/sinat_36246371/article/details/53709625


LinkedList、ArratList、Vector的区别


HashSet

HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性。

HashSet特点:

下面通过代码演示:

HashSet<String> set = new HashSet<String>();

    set.add("A");
    set.add("C");
    set.add("B");
    set.add("D");
    set.add("D");
    set.add("D");
    set.add("D");
    System.out.println(set);

    set.remove("A"); // 不能通过索引位置来删除元素
    System.out.println(set);
    System.out.println(set.size());

    System.out.println(set.contains("B"));

    System.out.println(set.isEmpty());

    HashSet set2 = (HashSet) set.clone();// clone一个HashSet
    System.out.println(set2);

    set.add("E");
    set.add("Z");
    set.add("X");
    set.add("F");

    Iterator it = set.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }

输出为:

[A, B, C, D]
[B, C, D]
3
true
false
[B, C, D]
BCDEFXZ

Map

HashMap

HashMap存的是键值对(Key-value),键不能重复,值可以重复

下面是代码演示:

HashMap<String, String> map = new HashMap<String, String>();
    map.put("B", "周一");
    map.put("A", "周二");
    map.put("B", "周三"); // 因为键重复,所以值覆盖
    System.out.println(map.get("B"));
    System.out.println(map.get("C"));

    // 获取map里面所有的值,遍历出所有值
    Collection<String> values = map.values();
    for (String value : values) {
        System.out.print(value + " ");
    }
    System.out.println();

    // 遍历出所有键
    Set<String> keySet = map.keySet();
    System.out.println(keySet);

    // 通过key的Set集合 获取到所有的value
    for (String key : keySet) {
        System.out.println(map.get(key));
    }

输出为:

周三
null
周二 周三
[A, B]
周二
周三

HashMap原理:

哈希算法--hashCode

HashMap如何判断某个key是否是重复的?
首先会获取key的hashCode,判断map中是否存在hashCode相同的key,如果不一致则直接存储键值对;如果一致,将继续用key的equal判断该key在map中是否存在一样的,如果存在, 则不存储,只是将值覆盖,否则就存储

注意点:


Collection和Collections的区别

Collections提供了以下方法对List进行排序操作

代码演示:

ArrayList nums = new ArrayList();
nums.add(8);
nums.add(-3);
nums.add(2);
nums.add(9);
nums.add(-2);
System.out.println(nums);

Collections.reverse(nums);
System.out.println(nums);

Collections.sort(nums);
System.out.println(nums);

Collections.shuffle(nums);
System.out.println(nums);

// 下面只是为了演示定制排序的用法,将int类型转成string进行比较
Collections.sort(nums, new Comparator() {
    @Override
    public int compare(Object o1, Object o2) {
    // TODO Auto-generated method stub
    String s1 = String.valueOf(o1);
    String s2 = String.valueOf(o2);
    return s2.compareTo(s1);
    }
});
System.out.println(nums);
}

输出为:

[8, -3, 2, 9, -2]
[-2, 9, 2, -3, 8]
[-3, -2, 2, 8, 9]
[9, 8, -2, 2, -3]
[9, 8, 2, -3, -2]

代码演示:

ArrayList num = new ArrayList();
num.add(3);
num.add(-1);
num.add(-5);
num.add(10);
System.out.println(num);

System.out.println(Collections.max(num));

System.out.println(Collections.min(num));

Collections.replaceAll(num, -1, -7);
System.out.println(num);

System.out.println(Collections.frequency(num, 3));

Collections.sort(num);
System.out.println(num)
System.out.println(Collections.binarySearch(num, 3));

输出为:

[3, -1, -5, 10]
10
-5
[3, -7, -5, 10]
1
[-7, -5, 3, 10]
2

Collections中几乎对每个集合都定义了同步控制方法,例如 SynchronizedList(), SynchronizedSet()等方法,来将集合包装成线程安全的集合。下面是Collections将普通集合包装成线程安全集合的用法,例如:

Collection c = Collections.synchronizedCollection(new ArrayList());
List list = Collections.synchronizedList(new ArrayList());
Set s = Collections.synchronizedSet(new HashSet());
Map m = Collections.synchronizedMap(new HashMap());
设置不可变(只读)集合

Collections提供了三类方法返回一个不可变集合,

代码演示:

List lt = Collections.emptyList();

Set st = Collections.singleton("avs");

Map mp = new HashMap();
mp.put("a", 100);
mp.put("b", 200);
mp.put("c", 150);
Map readOnlyMap = Collections.unmodifiableMap(mp);

// 下面会报错
lt.add(100);
st.add("sdf");
mp.put("d", 300);

请尊重作者劳动成果,转载请标明原文链接:https://www.jianshu.com/p/d2c1f7b5e729

上一篇 下一篇

猜你喜欢

热点阅读