集合
1、基本数据类型对象包装类
为了方便操作基本数据类型值,将其封装成了对象,在对象中定义了属性和行为丰富了该数据的操
作。
用于描述该对象的类就称为基本数据类型对象包装类。
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
该包装对象主要用于基本类型和字符串之间的转换
基本类型-->字符串 方法:
1. 基本类型数值+""
2. 用String类中的静态方法valueOf(基本类型数值);
字符串-->基本类型
1. 使用包装类中的静态方法xxx parseXxx("xxx");
int parseInt(String str);
long parseLong(String str);
boolean parseBoolean(String str);
只有Character没有parse方法。
2. 用Integer的静态方法valueOf(String s);
整数具备不同的进制体现。
十进制-->其他进制方法:
String toBinaryString(int i); //二进制
String toOctalString(int i); //八进制
String toHexString(int i); //十六进制
String toString(int i,int radix); //i的radix次方进制
————————————————————————————————————————————————————————————————————
import java.util.Arrays;
public class StringSorted {
/**
*对一个字符串中的数值进行从小到大的排序。"20 78 9 -7 88 36 29"
*/
public static void main(String[] args) {
String str = "20 78 9 -7 88 36 29";
String[] ss = str.split(" +");
int[] ins = new int[ss.length];
for (int i = 0; i < ins.length; i++) {
ins[i] = Integer.parseInt(ss[i]);
}
Arrays.sort(ins);
for(int i:ins)
System.out.print(i+" ");
}
}
————————————————————————————————————————————————————————————————————
2、集合类
集合类的由来:
对象用于封装特有数据,对象多了需要存储;如果对象的个数不确定,就使用集合容器进行存储。
集合特点:
1. 用于存储对象的容器。
2. 集合的长度是可变的。
3. 集合中不可以存储基本数据类型值。
集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。
P.S.
数组和集合类同是容器,有何不同?
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
3、 List Set
Collection
|--List:有序(存入和取出的顺序一致),元素都有索引(角标),允许重复元素。
|--Set:元素不能重复,无序。
List:特有的常见方法。
有一个共性特点就是都可以操作角标。
1、添加
void add(index,element);
void addAll(index,collection);
2、删除
Object remove(index);
3、修改
Object set(index,element);
4、获取:
Object get(index);
int indexOf(object);
int lastIndexOf(object);
List subList(from,to);
List集合可以完成对元素的增删改查。
PS:
在迭代器过程中,不要使用集合方法操作元素(增删改),容易出现异常:
java.util.ConcurrentModificationException。
可以使用Iterator接口的子接口ListIterator来完成在迭代中对元素进行更多的操作。
Iterator 可实现删除功能
ListIterator 可实现增删改功能功能
————————————————————————————————————————————————————————————————————
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class CollectIteratorDemo {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<Integer>();
for (int i = 0; i < 10; i++)
al.add(i);
System.out.println("al: " + al);
for(Iterator<Integer> it = al.iterator() ;
it.hasNext();){
if(it.next() == 2)
it.remove();
}
System.out.println("al: " + al);
for (ListIterator<Integer> it = al.listIterator(); it.hasNext();) {
if (it.next() == 2) {
it.set(8);
it.add(4);
it.add(4);
}
}
System.out.println("al: " + al);
}
}
————————————————————————————————————————————————————————————————————
4、 Vector、ArrayList、LinkedList
List:
|--Vector:内部是数组数据结构,是同步的。增删,查询都很慢。
|--ArrayList:内部是数组数据结构,是不同步的,替代了Vector。替代了Vector,查询的速度快。
|--LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。
LinkedList方法:
addFirst();
addLast();
jdk1.6版本后新方法:
offerFirst(); 与addFirst方法没有区别。
offerLast(); 与addLast方法没有区别。
---------------------------------------------------------
getFirst();//获取但不移除,如果链表为空,抛出NoSuchElementException。
getLast();
jdk1.6版本后新方法:
peekFirst();//获取但不移除,如果链表为空,返回null。
peekLast();
--------------------------------------------------------
removeFirst();//获取并移除,如果链表为空,抛出NoSuchElementException。
removeLast();
jdk1.6版本后新方法:
pollFirst();//获取并移除,如果链表为空,返回null;
pollLast();
————————————————————————————————————————————————————————————————————
import java.util.LinkedList;
public class StackDemo {
/**
* 请使用LinkedList来模拟一个堆栈或者队列数据结构。 堆栈:先进后出 First In Last Out FILO 队列:先进先出
* First In First Out FIFO
*/
public static void main(String[] args) {
StackSimu s = new StackSimu();
for (int i = 0; i < 5; i++)
s.push(i);
while (!s.isEmpty())
System.out.println(s.pop());
}
}
class StackSimu {
private LinkedList<Integer> ll = new LinkedList<Integer>();// 封装一个链表
public boolean push(int i) {// 进栈
ll.offerFirst(i);// 添加在头部,在底部
// ll.add(i);
return true;
}
public int pop() {// 出栈
// if(ll.size()>0)
return ll.removeFirst();
}
public boolean isEmpty() {
return (ll.size() == 0);
}
}
————————————————————————————————————————————————————————————————————
5、Set:
Set:元素不可以重复,是无序。
Set接口中的方法和Collection一致。
|--HashSet:内部数据结构是哈希表,是不同步的。
|--TreeSet:可以对Set集合中的元素进行排序,是不同步的
哈希表判断元素相同的原理:
1. 首先判断两个元素的哈希值是否相同。
如果相同,再判断两个对象的内容是否相同。
2. 判断哈希值相同,其实判断的是对象的HashCode()返回的值是否相等。判断内容相同,用的是equals方法。
P.S.
如果哈希值不同,不需要判断equals。
6、LinkedHashSet
HashSet实现数据的唯一性,Linked实现数据的有序性
7、TreeSet
TreeSet判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
TreeSet对元素进行排序的方式一: 让元素自身具备比较功能,元素就需要实现Comparable接口,
覆盖compareTo方法。
如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
可以使用TreeSet集合第二种排序方式:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。
P.S.
如果自定义类实现了Comparable接口,并且TreeSet的构造函数中也传入了比较器,那么将以比较器
的比较规则为准。
与TreeSet底层实现比较有关的底层代码
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
由此可见,只有当比较器为空时,才会调用对象的自然属性进行比较。比较器是TreeSet的一个成员
TreeSet集合的底层是二叉树进行
————————————————————————————————————————————————————————————————————
import java.util.Comparator;
import java.util.TreeSet;
/**
* 10、声明类Student,包含3个成员变量:name、age、score,创建5个对象装入TreeSet,
* 按照成绩排序输出结果(考虑成绩相同的问题)。
*/
public class Test10 {
public static void main(String[] args) {
// 创建集合,并传递比较器
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int result = 1;
if ((result = (o1.getScore() - o2.getScore())) == 0) {// 按分数排序
if ((result = (o1.getAge() - o2.getAge())) == 0) {// 分数相同时按年龄
result = o1.getName().compareTo(o2.getName());// 分数、年龄都相同时按姓名排序
}
}
return result;
}
});
// 创建5个对象,并存入集合
ts.add(new Student("Lucy", 15, 90));
ts.add(new Student("Lily", 15, 92));
ts.add(new Student("Pote", 15, 90));
ts.add(new Student("Scoe", 17, 90));
ts.add(new Student("Shay", 18, 94));
// 遍历集合输出
for (Student s : ts)
System.out.println(s);
}
}
//声明类Student,包含3个成员变量
class Student implements Comparable{
private String name;
private int age;
private int score;
public Student(String name, int age, int score) {
super();
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "姓名 :" + name + ",年龄: " + age + ",分数: " + score;
}
@Override
public int compareTo(Object o) {
return -1;
}
}
————————————————————————————————————————————————————————————————————
8、Map
Map:一次添加一对元素,Collection一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实Map集合中存储的就是键值对。
map集合中必须保证键的唯一性。
P.S. 关于泛型相关的知识请参看Java高级知识笔记:http://bbs.itheima.com/thread-107670-1-1.html。
常用方法:
1、添加
value put(key,value):返回前一个和key关联的值,如果没有返回null。
2、删除
void clear():清空map集合。
value remove(Object key):根据指定的key删除这个键值对。
3、判断
boolean containsKey(key);
boolean containsValue(value);
boolean isEmpty();
4、获取
value get(key):通过键获取值,如果没有该键返回null。
可以通过返回null,来判断是否包含指定键。
int size():获取键值对个数。
5、遍历Map的方法:
Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的 Set 视图。
Set<K> keySet()
返回此映射中包含的键的 Set 视图。
Collection<V> values()
返回此映射中包含的值的 Collection 视图。
Map常用的子类:
|--Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
|--Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
|--HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。
|--TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。
hashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。
使用LinkedHashMap则是跟原来存入的顺序是一致的。
————————————————————————————————————————————————————————————————————
/**
* 需求:统计输入的字符串,如 "abcaab" 以a(3)b(2)c(1)的形式输出
* 分析: 1 字符与字符个数属于对应关系,可用Map<String,Integer>
* 2 输出字母是自然排序,所以考虑使用TreeMap
*/
package fmi1;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class CharacterCount {
public static void main(String[] args) {
// TODO Auto-generated method stub
//建立接收键盘输入的字符串
System.out.println("请输入字符串:");
String line = new Scanner(System.in).nextLine();
//建立集合Map
TreeMap<Character, Integer> tm = new TreeMap<Character,Integer>();
//将输入字符串转成数组
char[] chs = line.toCharArray();
//遍历字符串,将字符存入集合Map,若字符key已存在,则value加1,否则,value = 1
for(char ch:chs ){
//根据键获取集合的值,判断字符的个数
Integer value = tm.get(ch);
if(null == value){//没有对应键值对
value = 1;
}
else
value++;
//将更新后的键值关系存至Map
tm.put(ch, value);
}
//遍历Map,输出键值对
StringBuilder sb = new StringBuilder("");
Set<Character> s = tm.keySet();
for(Character ch:s){
sb.append(ch).append("(").append(tm.get(ch)).append(")");
}
System.out.println(sb.toString());
}
}
————————————————————————————————————————————————————————————————————
9、Collections工具类
10、Arrays:集合框架的工具类,里面的方法都是静态的。
重点:List asList(数组)将数组转成集合。
好处:可以使用集合的方法操作数组。
P.S.
数组的长度是固定的,所以对于结合的增删方法是不可以使用的,否则,会发生
UnsupportedOperationException。
数组转集合,用asList方法。
如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
集合转数组
使用的就是Collection接口中的toArray方法。
集合转成数组,可以对集合中的元素操作的方法进行限定,不允许对其进行增删。
toArray方法需要传入一个指定类型的数组。
长度该如何定义呢?
如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同的size的数组。
如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为
null。
所以建议,最后长度就指定为,集合的size。