java基础汇总(三)

来源:互联网 发布:淘宝双11外围报名条件 编辑:程序博客网 时间:2024/05/18 01:15

今天又把java基础看了点,但是前几天看的没有总结,今天先把这些作为草稿保存,日后再好好整理。关于java集合的内容在网上很多,但是看了好多遍后还是挺容易忘记的,所以闲下来就随便写点以免忘记。此文并没有深入去了解容器的实现,只是对于容器的基本使用及方法做了记录,只是为了日后有个地方可以方便查阅

java集合

 java集合类中主要有Collection和Map接口,其中Collection派生了List与Set集合。

1.java 集合只能存放引用类型数据,集合与数组的比较:数组长度是不可变的,集合是可变的,数组可以存放基本数据类型也可以存放引用数据类型,集合只能存放引用数据类型。

2.Collection其主要的子接口有
List<E>:集合中的元素按照索引值来排序,允许存放重复的元素。
Queue<E>:队列接口,通常以FIFO的方式排序各个元素。
Set<E>:集合中的元素不按特定方式排序,不能存在重复元素,但它的有些实现类能对集合中的元素按照特定方式排序。
SortedSet<E>:可以对集合中的元素进行排序。
Collection接口定义
public interface Collection<E>extends Iterable<E>

3.Collection接口的基本(抽象)方法主要有以下方法:

boolean     add(E e)
boolean     addAll(Collection<? extends E> c)
void        clear()
boolean     contains(Object o)
boolean     containsAll(Collection<?> c)
boolean     equals(Object o)
int         hashCode()
boolean     isEmpty()
Iterator<E> iterator()

boolean     remove(Object o) 

boolean     removeAll(Collection<?> c)
boolean     retainAll(Collection<?> c)
int         size() 

 Object[]   toArray()
<T> T[]      toArray(T[] a)对于其中的几个比较常用的就不写代码了,对于retainAll(Collection<?> c)方法主要意思就是将原来集合中的数据只保留集合C中存在的元素

例子:

package CollectionTest;import java.util.Collection;import java.util.LinkedList;public class testlinkedlist {public static void main(String[] args) {LinkedList<String> c1 = new LinkedList<String>();Collection<String> c2 = new LinkedList<String>();c1.add("11");c1.add("222");c1.add("ee");c2.add("ee");c2.add("ff");c2.add("we");c2.add("fefe");System.out.println("调用retainAll方法前");System.out.println(c1);c1.retainAll(c2);System.out.println("调用retainAll方法后");System.out.println(c1);}}
结果:

调用retainAll方法前[11, 222, ee]调用retainAll方法后[ee]
然后就是对于集合来说,将集合转换为数组也是很常用的方法,转换成数组有两种方法,但是Object[]   toArray() 转换成的数组为object类型的,不能强制转换为其他子类类型,那我们来看看toArray(T[] a)的用法。

package CollectionTest;import java.util.Collection;import java.util.LinkedList;public class testlinkedlist {public static void main(String[] args) {Collection<String> c1 = new LinkedList<String>();c1.add("11");c1.add("222");c1.add("ee");String[] s = new String[c1.size()];c1.toArray(s);System.out.println("转换为数组s");for (int i = 0; i < s.length; i++) {System.out.println(s[i]);}}}
结果
转换为数组s11222ee
4.接口List

对于接口List作为Collection的子接口,我们更关心的是其在Collection的基础上增加了什么功能。让我们看一下其所增加的方法。

 void              add(int index,E element)

 boolean           addAll(int index,Collection<? extends E> c) 

 E                 get(int index)
 int               indexOf(Object o)第一次出现对象o的位置,如果不存在则返回-1;

 int               lastIndexOf(Object o)

ListIterator<E>    listIterator()

ListIterator<E> listIterator(int index)
 E                 remove(int index)
 E                 set(int index,E element)

 List<E>           subList(int fromIndex, int toIndex)

从上面的方法中我们可以看出在List接口中主要添加了有位置索引的方法。可以在指定位置进行操作。

listiterator

1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。
2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。
3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator不可以。
4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

package CollectionTest;import java.util.LinkedList;import java.util.ListIterator;public class testlinkedlist {public static void main(String[] args) {LinkedList<String> c1 = new LinkedList<String>();c1.add("11");c1.add("222");c1.add("ee");ListIterator<String> listIterator=c1.listIterator();//测试了一下可以将参数0,1,2,3传入,但是当是3的时候没有值输出。while(listIterator.hasNext()) {System.out.println(listIterator.next());}}}<pre name="code" class="java">

结果:

11222ee
对于sublist方法,我们举个例子看一下

package CollectionTest;import java.util.ArrayList;import java.util.Collection;import java.util.List;public class test1 {public static void main(String args[]) {Collection<String> c1 = new ArrayList<String>();ArrayList<String> lStrings = new ArrayList<String>();c1.add("1");c1.add("2");c1.add("3");c1.add("a");lStrings.add("a");lStrings.add("b");lStrings.add("c");lStrings.addAll(1, c1);// 在位置为1的地方插入集合c1(从0开始计数)List<String> subStrings = lStrings.subList(1, 3);// 截取子集合(包含位置1不包含位置3)//lStrings.add("会出错!");//subStrings.add("这样就可以,而且还改变了原来的集合内容");System.out.println("subStrings:"+subStrings);System.out.println("lStrings:"+lStrings);}}

结果:

subStrings:[1, 2]lStrings:[a, 1, 2, 3, a, b, c]
但是在调用这个方法的时候我想了个问题就是这个子集合是独立的内存空间还是只是创建了个对对象部分的引用。我就修改了程序,当把注释去掉加上
lStrings.add("会出错!");
但是报出了错误:java.util.ConcurrentModificationException大家可以去看看网上有人提出这个错误,大多数是在利用迭代器时,用集合本身直接操作元素导致的,而利用迭代器来操作应该没有问题。

但是如果只把其下面的去掉注释,在子集合里操作是没有问题的,子集合添加了元素后,原来的集合也会发生改变。

结果为:

subStrings:[1, 2, 这样就可以,而且还改变了原来的集合内容]lStrings:[a, 1, 2, 这样就可以,而且还改变了原来的集合内容, 3, a, b, c]
ArrayList类定义

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

ArrayList类允许所有的元素,包括null,ArrayList类是数组列表类,允许元素快速访问,但是对于插入操作与删除操作较慢,在插入一个元素时,需要将插入位置及其后面的元素依次后移。
其在接口List基础之上扩增的常用方法:

void ensureCapacity(int minCapacity) //增大实际容量,确保可以容纳指定的这个最小值minCapacity这么多的元素
void  removeRange(int fromIndex, int toIndex)//删除fromIndex到toIndex范围的集合,toIndex位置的元素除外

void trimToSize()//将当前ArrayList的容量调整为当前的实际大小。


LinkedList是链表类,对于它来说随机访问某个位置的数据不如ArrayList方便,但是对于插入、删除操作频繁的情况来说,其效率要高。

其定义:

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable
对于LinkedList来说,其增加的方法多是对于头跟尾的操作,这里记录几个,其他的都比较类似。

void         addFirst(E e)
void         addLast(E e)
E            getFirst()
E              getLast()
boolean     offerFirst(E e)//头部插入

boolean     offerLast(E e)//尾部插入

E           peekFirst() //获取第一个元素但不删除 同peek() 与element()方法类似

E           peekLast()//获取最后一个元素但不删除

pollFirst() poll() pop()  removeFirst() remove() 几个方法是获取第一个元素并在链表中删除。与之对应的有获取最后一个元素并删除 removeLast() pollLast()

boolean    removeFirstOccurrence(Object o)//从此链表中删除第一次出现的指定元素。如果不包含该元素则不作修改。

boolean    removeLastOccurrence(Object o) //从此链表中最后一次出现的指定元素。如果链表不包含该元素,则不作更改。


Set接口

set是一个不包含重复元素的collection,set允许包含Null元素,但只允许有一个null元素。

public interface Set<E> extends Collection<E>

HashSet类

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable

对于HashSet类来说,它存放的元素没有顺序,其不是线程同步的。对于继承AbstractSet 是继承了hashcode以及equals几个方法,对于没有重写这两个方法的自定义类来说,如果用hashset来存放对象时,是不会体现set相同元素只有一个的特性。要实现相同元素只有一个则必须重写这两个方法。

实例:

package CollectionTest;import java.util.HashSet;import java.util.Iterator;public class HashSetTest {  public static void main(String args[]){  HashSet<person> ha=new HashSet<person>();  ha.add(new person("小明",12));  ha.add(new person("小李",12));  ha.add(new person("小强",12));  ha.add(new person("小明",12));  ha.add(new person("小智",12));  ha.add(new person("小明",12));  Iterator<person> iterator=ha.iterator();  while(iterator.hasNext()){  System.out.println(iterator.next());    }  }}class person{public String name;public int age;public String getName() {return name;}public void setName(String name) {this.name = name;} public person (String name,int age) {this.name=name;this.age=age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString(){return ("姓名:" +name+",年龄:"+age);}/*@Overridepublic int hashCode(){final int prime=13;int result=13;result=prime*result+((name==null)?0:name.hashCode());result=prime*result+age;return result;}@Overridepublic boolean equals(Object object){if(this==object){return true;}if(object==null){return false;}if(!(object instanceof person)){return false;}person per=(person)object;if(per.name==this.name&&per.age==this.age){return true;}else {return false;}}*/}


当没有重写这两个方法时(将这两个方法注释掉)结果为:

姓名:小明,年龄:12姓名:小智,年龄:12姓名:小李,年龄:12姓名:小明,年龄:12姓名:小强,年龄:12姓名:小明,年龄:12
重写这两个方法后结果为:

姓名:小明,年龄:12姓名:小强,年龄:12姓名:小智,年龄:12姓名:小李,年龄:12


TreeSet
public class TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable
对于TreeSet我们在用的时候就是知道其排序的功能,但是对于自定义类型来说要实现compareable接口中的compareTo方法,如果没有实现该接口则会报 java.lang.ClassCastException的错误。
实例:

package CollectionTest;import java.util.Iterator;import java.util.TreeSet;public class TreeSetTest {public static void main(String args[]) {TreeSet<people> ha = new TreeSet<people>();ha.add(new people("小明", 12));ha.add(new people("小李", 13));ha.add(new people("小强", 11));ha.add(new people("小明", 12));ha.add(new people("小智", 12));ha.add(new people("小明", 12));Iterator<people> iterator = ha.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}}class people implements Comparable<people>{public String name;public int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public people(String name, int age) {this.name = name;this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String toString() {return ("姓名:" + name + ",年龄:" + age);}@Overridepublic int hashCode() {final int prime = 13;int result = 13;result = prime * result + ((name == null) ? 0 : name.hashCode());result = prime * result + age;return result;}@Overridepublic boolean equals(Object object) {if (this == object) {return true;}if (object == null) {return false;}if (!(object instanceof people)) {return false;}people per = (people) object;if (per.name == this.name && per.age == this.age) {return true;} else {return false;}}@Overridepublic int compareTo(people o) {if(this.age>o.age){return 1;}else if(this.age<o.age){return -1;}else {return this.name.compareTo(o.name);}}}
结果为:

姓名:小强,年龄:11姓名:小明,年龄:12姓名:小智,年龄:12姓名:小李,年龄:13

对于TreeSet来说不用重写hashcode与equals你会发现其结果也是一样的,说明TreeSet在去重时并不是与HashSet一样通过hashcode找到位置,再通过equals函数来确定其唯一性的,TreeSet是通过重写的compareTo(object o)方法来进行排序的,并且也是通过这个方法去重的。去重取决于这个方法里的写法。

如果将上面的例子中的compareTo方法写成下面的样子:

public int compareTo(people o) {if(this.age>o.age){return 1;}else if(this.age<o.age){return -1;}else {return 0;}}
那么其结果就会是下面的样子:

姓名:小强,年龄:11姓名:小明,年龄:12姓名:小李,年龄:13
会将年龄相同的作为相同对象而去重。
TreeSet对象的部分方法

E  pollFirst() 获取第一个*(最小)元素,并删除

E  pollLast()  获取最后(最大)一个

NavigableSet<E> descendingSet() 将集合反序

SortedSet<E>  headSet(E toElement)返回小于给定元素的所有值的集合

SortedSet<E>   subSet(E fromElement, E toElement) 获取集合 包括开始,不包括toelement位置元素

NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 获取集合,设定取不取两端的值

SortedSet<E>  tailSet(E fromElement)

NavigableSet<E>  tailSet(E fromElement, boolean inclusive)

Iterator接口应该注意的是:用迭代器删除一个元素的时候,要在调用next()方法后再调用remove()方法。


Map接口

map接口并没有继承Collection接口,其定义如下:

public interface Map<K,V>
该接口中定义的部分方法:

boolean containsKey(Object key)

boolean containsValue(Object value)

Set<Map.Entry<K,V>> entrySet()

V get(Object key)

 Set<K> keySet()

V put(K key, V value)

void putAll(Map<? extends K,? extends V> m)

V remove(Object key) 

boolean  isEmpty()
V remove(Object key)

Collection<V>  values()
上面的方法大多数通过方法名就可以知道用法,注意的是在map内部定义了一个静态的接口,该接口封装了一个key-value,该接口的方法如下:

equals(Object o) 

K getKey() 

V getValue()

int hashCode()

V setValue(V value)

HashMap类

HashMap是非同步的,允许使用null值和null键

实例:

package TestMap;import java.util.HashMap;import java.util.Map;public class test1 { public static void main(String[] args) {Map<person, String> map=new HashMap<person, String>();map.put(new person("小明", 12), "ww");map.put(new person("小啊", 11), "aa");map.put(new person("小里", 13), "ss");map.put(new person("小值", 14), "ee");map.put(new person("小飞", 16), "ff");map.put(new person("小明", 12), "gg");for(Map.Entry<person, String> s:map.entrySet()){System.out.print(s.getKey().name+"  ");System.out.println(s.getValue());}}}class person{public String name;public int age;person(String name, int age){this.name=name;this.age=age;}public int hashCode () { final int prime=13;  int result=13; result=prime*result+((name==null)?name.hashCode():0); result=prime*result+age; return result;}public boolean equals(Object object) {if (this == object) {return true;}if (object == null) {return false;}if (!(object instanceof person)) {return false;}person per = (person) object;if (per.name == this.name && per.age == this.age) {return true;} else {return false;}}}
结果:

小值  ee小里  ss小明  gg小啊  aa小飞  ff
在这里,如果键值用的是自定义类型的类,那么要重写hashcode与equals方法。

TreeMap是进行了排序的,跟在set中理解TreeSet是一样的,所以如果想实现排序,那么作为键值的类型要实现comparable接口


0 0