IO流 - 二、缓冲区

二、缓冲区

提高了对数据的读写效率。

对应类:

BufferedWriter

BufferedReader

1、缓冲区单个字符读写

public class Demo6 {

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("demo.txt");
        BufferedReader bufr = new BufferedReader(fr);

        FileWriter fw = new FileWriter("buf_copy.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        int ch = 0;
        while((ch = bufr.read())!=-1) {
            bufw.write(ch);
        }
        bufw.close();
        bufr.close();

    }

}

2、缓冲区逐行读写

public class Demo6 {

    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("demo.txt");
        BufferedReader bufr = new BufferedReader(fr);

        FileWriter fw = new FileWriter("buf_copy.txt");
        BufferedWriter bufw = new BufferedWriter(fw);

        String line = null;

        while((line = bufr.readLine())!=null) {
            bufw.write(line);
            bufw.newLine();
            bufw.flush();
        }

        bufw.close();
        bufr.close();

    }

}

3、缓冲区 - 装饰设计模式

装饰设计模式:

对一组对象的功能进行增强时,就可以使用该模式解决问题。

public class Person {
    public void eat() {
        System.out.println("....eating...");
    }
}

//通过继承进行功能扩展
class NewPerson extends Person{
    public void eat() {
        System.out.println("befor...eating...");
        super.eat();
        System.out.println("after...eating");
    }
}

//通过装饰类进行功能扩展
class NewPerson2 {
    private Person p;
    NewPerson2(Person p){
        this.p = p;
    }
    void eat() {        
        System.out.println("befor...eating...");
        p.eat();
        System.out.println("after...eating");
    }
}

装饰和继承的区别:

Writer

|– TextWriter:用于操作文本

—– BufferedTextWriter:加入缓冲技术

|– MediaWriter:用于操作媒体

—– BufferedMediaWriter:加入缓冲技术

继承导致原有类的体系越来越臃肿,不够灵活。

class Buffered {
Buffered(Writer w){

}
}

装饰比继承更灵活。

4、缓冲区 - 装饰类 - LineNumberReader

public class Demo7 {

    public static void main(String[] args) throws IOException {

        FileReader fr = new FileReader("demo.txt");
        LineNumberReader lnr = new LineNumberReader(fr);

        String line = null;
        lnr.setLineNumber(100);
        while((line = lnr.readLine()) != null) {
            System.out.println(lnr.getLineNumber()+":"+line);
        }
    }

}

输出结果:
101:abc
102:cde

IO流 - 三、字节流

1、操作文件基本演示

public class Demo8 {

    public static void main(String[] args) throws IOException {

        //创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("demo.txt");

        //数据直接写入目标文件,没有缓冲区
        fos.write("aaaaaddfsdss".getBytes());

        fos.close();

    }

}

逐个字节读取

public class Demo9 {

public static void main(String[] args) throws IOException {

    FileInputStream fis = new FileInputStream("demo.txt");

    int ch = 0;
    while((ch = fis.read()) != -1) {
        System.out.println((char)ch);
    }

    fis.close();
}

}

逐个数组读取

public class Demo10 {

    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("demo.txt");

        byte[] buf = new byte[1024];
        int length = 0;

        while((length = fis.read(buf, 0, length)) != -1) {
            System.out.println(new String(buf,0,length));
        }

        fis.close();

    }

}

2、练习 - 复制mp3

直接复制

public class Demo11 {

    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("0.mp3");
        FileOutputStream fos = new FileOutputStream("1.mp3");

        byte[] buf = new byte[1024];
        int length = 0;

        while((length = fis.read()) != -1) {
            fos.write(buf,0,length);
        }

        fos.close();
        fis.close();
    }

}

高效复制

public class Demo11 {

    public static void main(String[] args) throws IOException {

        FileInputStream fis = new FileInputStream("0.mp3");
        BufferedInputStream bufis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream("1.mp3");
        BufferedOutputStream bufos = new BufferedOutputStream(fos);

        byte[] buf = new byte[1024];

        int length = 0;
        while((length = bufis.read(buf)) != -1) {
            bufos.write(buf, 0, length);
        }

        bufis.close();
        bufos.close();

    }
}

3、演示键盘录入

读取键盘录入的一个数据,并打印在控制台上。

键盘本身就是一个标准的输入设备。

对于java而言,对于这种输入设备都有相应的对象。

java.lang包里的 System类

public static finael InputStream in

“标准”输入流,不用关闭。

键盘录入:

public class Demo12 {
    public static void main(String[] args) throws IOException {
        InputStream in = System.in;
        int ch = in.read();
        System.out.println(ch);
    }
}

读取键盘录入:

public class Demo15 {

    public static void main(String[] args) throws IOException {

        InputStream in = System.in;
        int ch = 0;
        StringBuilder sb = new StringBuilder();
        while((ch=in.read())!=-1) {
            if(ch=='\r') 
                continue;
            if(ch=='\n') {
                String temp = sb.toString();
                if("over".equals(temp))
                    break;
                System.out.println(temp.toUpperCase());
                sb.delete(0, sb.length());
            } else {
                sb.append((char)ch);
            }
        }

    }

}

其它对象API

一、System类

System类中的方法和属性都是静态的。

常见方法:

long currentTimeMillis():获取当前时间的毫秒值

Properties getProperties():获取当前系统的属性信息

public class SystemApi {
    public static void main(String[] args) {

        long millisTime = System.currentTimeMillis();
        System.out.println(millisTime);

        Properties prop = System.getProperties();

        Set<String> nameSet = prop.stringPropertyNames();

        for(String name:nameSet) {
            String value = prop.getProperty(name);
            System.out.println(name+"::"+value);
        }


    }
}

二、Runtime类

Runtime:

没有构造方法摘要,说明该类不可以创建对象。

又发现该类有非静态方法,说明该类应该有提供的静态的返回该类对象的方法。

而且只有一个这种方法,说明Runtime类使用了单例设计模式。

public class RuntimeApi {

    public static void main(String[] args) throws IOException, InterruptedException {

        Runtime r = Runtime.getRuntime();

        Process p = r.exec("open -a Safari.app http://www.baidu.com");
        Thread.sleep(2000);
        p.destroy();
    }

}

三、Math类

常用方法:

double ceil():返回大于参数的最小整数。

double floor():返回小于参数的最大整数。

double round():返回四舍五入的整数。

max(a,b):返回最大值

pow(a,b):a的b次方

double random():返回大于等于0.0小于1.0的随机double值,与java.util中的Random类相似。

四、Date类

(一)、日期对象和毫秒值之间的转换

毫秒值–>日期对象

1、通过Date对象的构造方法 new Date(timeMills);

2、通过setTime方法。

目的是通过Date对象的方法,对该日期中的年月日等字段进行操作。

日期对象–>毫秒值

1、通过getTime方法。

目的是通过具体的数值进行运算。

public static void thord1() {
        //long time = System.currentTimeMillis();//1515489394135

        Date date1 = new Date();//将当前日期和时间封装成Date对象
        System.out.println(date1);//Tue Jan 09 17:16:34 CST 2018

        Date date2 = new Date(1515489367117l);//将指定毫秒封装成Date对象
        System.out.println(date2);//Tue Jan 09 17:16:07 CST 2018
}

(二)、日期对象转成字符串

public class DateDemo {

    public static void main(String[] args) {

        Date date = new Date();

        //获取日期格式对象。具备着默认的风格
        DateFormat dateFormat = DateFormat.getDateInstance();
        String str_date = dateFormat.format(date);
        System.out.println(str_date); //Jan 9, 2018

        DateFormat dateFormat2 = DateFormat.getDateTimeInstance();
        String str_date2 = dateFormat2.format(date);
        System.out.println(str_date2);//Jan 9, 2018 5:48:43 PM

        //其它风格 FULL LONG SHORT MEDIUM
        //DateFormat dateFormat3 = DateFormat.getDateInstance(DateFormat.FULL);//Tuesday, January 9, 2018

        //DateFormat dateFormat3 = DateFormat.getDateInstance(DateFormat.LONG);//January 9, 2018

        //DateFormat dateFormat3 = DateFormat.getDateInstance(DateFormat.SHORT);//1/9/18

        DateFormat dateFormat3 = DateFormat.getDateInstance(DateFormat.MEDIUM);//Jan 9, 2018

        String str_date3 = dateFormat3.format(date);
        System.out.println(str_date3);

        //日期和时间
        DateFormat dateFormat4 = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);//Jan 9, 2018

        String str_date4 = dateFormat4.format(date);
        System.out.println(str_date4);

        //自定义风格
        DateFormat dateFormats = DateFormat.getDateInstance();
        dateFormats = new SimpleDateFormat("yyyy-MM-dd");
        String str_date5 = dateFormats.format(date);
        System.out.println(str_date5);//2018-01-09


    }
}

(三)、字符串转成日期对象

使用的是DateFormat类中的parse方法。

public class DateFormatDemo {

    public static void main(String[] args) throws ParseException {

        //默认的日期字符串格式转成日期对象
        String str_date = "Jan 9, 2018 5:48:43 PM";
        DateFormat dateFormat = DateFormat.getDateInstance();
        Date date = dateFormat.parse(str_date);
        System.out.println(date);

        //将自定义的日期字符串格式转成日期对象
        String str_date2 = "2018--1--10";
        DateFormat dateFormat2 = DateFormat.getDateInstance(DateFormat.LONG);
        dateFormat2 = new SimpleDateFormat("yyyy--MM--dd");
        Date date2 = dateFormat2.parse(str_date2);
        System.out.println(date2);

    }

}

(四)、Date类 - 练习

public class Demo1 {

    public static void main(String[] args) throws ParseException {

        /**
         * 练习:
         * "2017.12.20"到"2018.1.10"中间相隔多少天
         * 
         * 思路:
         * 1、日期字符串转日期对象
         * 2、日期对象方法获取毫秒数
         * 3、毫秒数相减,再计算天数
         */

        String str_date1 = "2017.12.20";
        String str_date2 = "2018.1.10";

        //DateFormat dateFormat = DateFormat.getDateInstance();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");
        Date date1 = dateFormat.parse(str_date1);
        Date date2 = dateFormat.parse(str_date2);

        long date1Millis = date1.getTime();
        long date2millis = date2.getTime();

        int day = (int) Math.abs(date1Millis - date2millis)/1000/60/60/24;


        System.out.println(day);
    }

}

四、Calendar类

常见方法:

set()

get()

add():偏移

一、基本演示
public class CalendarDemo {

    public static void main(String[] args) {

        Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        int week = c.get(Calendar.DAY_OF_WEEK);

        System.out.println(year+"年"+month+"月"+day+"日"+getWeek(week));

    }

    private static String getWeek(int i) {
        String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        return weeks[i];
    }
}
二、练习
public class CalendarDemo {

    public static void main(String[] args) {

        Calendar c = Calendar.getInstance();
        //指定日期
        c.set(2018, 0, 20);
        showDate(c);

        //日期偏移
        c.add(Calendar.YEAR, 2);
        showDate(c);

    }

    public static void showDate(Calendar c) {
        //Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int day = c.get(Calendar.DAY_OF_MONTH);
        int week = c.get(Calendar.DAY_OF_WEEK);

        System.out.println(year+"年"+month+"月"+day+"日"+getWeek(week));
    }

    private static String getWeek(int i) {
        String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        return weeks[i];
    }

}

集合框架五 - 工具类

五、集合框架 - 工具类

Utilities

|– Collections

|– Arrays

1、Collections - 排序

需求:对有重复元素的集合排序。

public class Demo1 {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();

        list.add("afgds");
        list.add("jlojaio");
        list.add("haljasld");
        list.add("xjvis");
        list.add("afgds");

        System.out.println(list);

        //对list集合进行指定顺序的排序。
        Collections.sort(list);
        System.out.println(list);

        //对list按长度排序,传入自定义比较器
        Collections.sort(list,new ComparatorByLength());
        System.out.println(list);

    }

}

public class ComparatorByLength implements Comparator<String> {

    @Override
    public int compare(String o1, String o2) {
        int temp = o1.length() - o2.length();
        return temp == 0 ? o1.compareTo(o2) : temp;
    }

}

输出结果:
[afgds, jlojaio, haljasld, xjvis, afgds]
[afgds, afgds, haljasld, jlojaio, xjvis]    

自定义Collections工具类的static sort(List list)

public static <T extends Comparable<? super T>> void mysort(List<T> list) {

    for (int i = 0; i < list.size()-1; i++) {
        for (int j = i+1; j < list.size(); j++) {
            if(list.get(i).compareTo(list.get(j)) > 0) {
                /*
                T temp = list.get(i);
                list.set(i, list.get(j));
                list.set(j, temp);
                */
                Collections.swap(list, i, j);
            }
        }
    }


}

自定义Collections工具类的static sort(List list, Comparator<? super T> c)

public static <T> void mySort(List<T> list,Comparator<? super T> comp) {
        for (int i = 0; i < list.size()-1; i++) {
            for (int j = i+1; j < list.size(); j++) {
                if(comp.compare(list.get(i), list.get(j)) > 0) {
                    Collections.swap(list, i, j);
                }
            }
        }
    }

2、Collections - 折半&最值

折半查找,必须是对有序元素。

public class Demo2 {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();

        list.add("afgds");
        list.add("jlojaio");
        list.add("haljasld");
        list.add("xjvis");
        list.add("afgds");

        System.out.println(list);

        Collections.sort(list);

        int index = Collections.binarySearch(list, "afgds");

        System.out.println(index);

    }    
}

输出结果:
[afgds, jlojaio, haljasld, xjvis, afgds]
0

最值:有没有序都可以。

public class Demo2 {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();

        list.add("afgds");
        list.add("jlojaio");
        list.add("haljasld");
        list.add("xjvis");
        list.add("afgds");

        System.out.println(list);

        //取最大值
        String max = Collections.max(list);
        System.out.println("max:"+max);

        //取最长值
        String longest = Collections.max(list, new ComparatorByLength());
        System.out.println("longest:"+longest);

    }

}

3、Collections - 逆序&替换

逆序:reverseOrder方法,返回一个比较器,可以将具备自然排序的集合进行逆序。

public class Demo3 {

    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());

        ts.add("afgds");
        ts.add("jlojaio");
        ts.add("haljasld");
        ts.add("xjvis");
        ts.add("afgds");

        System.out.println(ts);

    }

}    

输出结果:倒序排列
[xjvis, jlojaio, haljasld, afgds]

也可对已有的比较器进行逆转

public class Demo3 {

    public static void main(String[] args) {

        TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));

        ts.add("afgds");
        ts.add("jlojaio");
        ts.add("haljasld");
        ts.add("xjvis");
        ts.add("afgds");

        System.out.println(ts);
    }

}

输出结果:从长到短排列
[haljasld, jlojaio, xjvis, afgds]

static boolean replaceAll(List list, T oldVal, T newVal) 使用另一个值替换列表中出现的所有某一指定值。

public class Demo4 {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();

        list.add("afgds");
        list.add("jloj");
        list.add("halj");

        System.out.println(list);

        Collections.replaceAll(list, "halj", "haojie");

        System.out.println(list);
    }

}

输出结果:
[afgds, jloj, halj]
[afgds, jloj, haojie]

4、Collections - 其它方法&将非同步集合转成同步集合的方法

使用指定元素替换指定列表中的所有元素。

static <T> void    fill(List<? super T> list, T obj) 

使用默认随机源对指定列表进行置换。随机排序,洗牌

static void    shuffle(List<?> list) 

返回指定 collection 支持的同步(线程安全的)collection。

static <T> Collection<T> synchronizedCollection(Collection<T> c) 

返回指定列表支持的同步(线程安全的)列表。
static List synchronizedList(List list)

返回由指定映射支持的同步(线程安全的)映射。

static <K,V> Map<K,V>    synchronizedMap(Map<K,V> m) 

返回指定 set 支持的同步(线程安全的)set。

static <T> Set<T>    synchronizedSet(Set<T> s) 

5、Arrays - toString方法

Arrays.toString方法

public class Demo1 {

    public static void main(String[] args) {

        int[] arr = {3,2,1,4,5,6};
        System.out.println(Arrays.toString(arr));
    }

}

经典实现

public static String toString(int[] a) {
    if (a == null)
        return "null";
    int iMax = a.length - 1;
    if (iMax == -1)
        return "[]";

    StringBuilder b = new StringBuilder();
    b.append('[');
    for (int i = 0; ; i++) {
        b.append(a[i]);
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}

6、Arrays - asList方法

将数组转成集合

static <T> List<T> asList(T... a) 

好处:可以使用集合中的方法来操作数组中的元素,除了改变长度的方法。

a、注意:数组的长度是固定的,所以对于集合的增删方法是不可以使用的。否则会发生UnsupportedOperationException

public class Demo2 {
    public static void main(String[] args) {

        String[] arr = {"aaa","bbb","ccc"};

        List<String> list = Arrays.asList(arr);

        boolean b = list.contains("aaa");

        System.out.println(b);

    }
}

b、如果数组中的元素是对象,那么转成集合时,直接将数组中的对象元素,作为集合中的元素进行存储。

如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储,因为集合中只能存储对象,而不能存储基本类型数据。

public class Demo3 {
    public static void main(String[] args) {

        int[] arr = {31,22,44,12};

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

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

    }
}

输出结果:
1

7、Collection-toArray方法

集合转数组:可以对集合中的元素操作的方法进行限定,不允许对其增删。

使用的是Collecion接口中的toArray方法

toArray方法需要传入一个指定类型的数组。

如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。

如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其它位置默认为null。

建议,最好长度就指定为集合的size。

public class Demo4 {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("ab3");
        list.add("sds");
        list.add("asfa");

        String[] arr = list.toArray(new String[5]);

        System.out.println(Arrays.toString(arr));

    }

}

输出结果:
[ab3, sds, asfa, null, null]

8、集合框架 - jdk5.0特性 - ForEach循环

public class Demo5 {

    public static void main(String[] args) {

        /**
         * foreach语句:
         * 格式:
         * for(类型 变量: Collection集合|数组){
         * 
         * }
         * 
         * 传统for循环和高级for循环的区别:
         * 传统for循环可以对语句执行很多次,因为可以控制循环的增量和条件。
         * 高级for循环是一种简化形式,必须有遍历的目标,可以是数组,也可以是Collecion单列集合。
         * 
         * 对数组的遍历,如果仅仅是为了获取数组中的元素,可以使用高级for循环。
         * 如果要对数组的角标进行操作建议使用传统for循环。
         */

        List<String> list = new ArrayList<String>();

        list.add("abc");
        list.add("def");
        list.add("ghi");
        list.add("jkl");

        //迭代器
        Iterator<String> it = list.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

        //高级for循环,通常只用于遍历,简化书写
        for(String s : list) {
            System.out.println(s);
        }

        //遍历数组
        int[] arr = {3,8,2,1,7};
        for(int i : arr) {
            System.out.println(i);
        }

        //高级for循环遍历map集合,要先把map集合转为单列集合。
        Map<Integer,String> map = new HashMap<Integer,String>();

        map.put(3, "zhangsan");
        map.put(4, "lisi");
        map.put(5, "wangwu");
        map.put(7, "zhaoliu");

        for(Integer key : map.keySet()) {
            String value = map.get(key);
            System.out.println(key+":"+value);
        }

        for(Map.Entry<Integer, String> merryEntry : map.entrySet()) {
            Integer key = merryEntry.getKey();
            String value = merryEntry.getValue();
            System.out.println(key+"::"+value);
        }

    }

}

9、集合框架 - jdk5.0特性 - 函数可变参数

public class Demo6 {

    public static void main(String[] args) {

        int sum = newAdd(5,1,4,7,3);
        System.out.println("sum="+sum);

        int sum1 = newAdd(3,5,2,5,3,2,2);
        System.out.println("sum1="+sum1);

    }

    /**
     * 函数是可变参数。
     * 其实就是一个数组,但是接收的是数组元素。
     * 自动将这些元素封装为数组。简化了调用者的书写。
     * 注意:可变参数类型,必须定义参数列表的结尾。
     */

    private static int newAdd(int a,int... arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum+=arr[i];
        }
        return sum;
    }

}

集合框架四 - Map集合

四、集合框架 - Map集合

1、集合特点&常用方法

Collection:一次添加一个元素,集合称为单列集合。

Map:一次添加一对元素,存储的是键值对,集合中必须保证键的唯一性。

常用方法:

添加:

value put(key,value):返回前一个和key关联的值,如果没有返回null

删除:

void clear():清空map集合
value remove(key):根据指定的key删除这个键值对,返回被删除键值对的value。

判断:

boolean containskey(key)
boolean containsValue(value)
boolean isEmpty()

获取:

value get(key):通过键获取值,如果没有该键返回null。因此,可以通过返回null,来判断是否包含指定键。
int size():获取键值对的个数。

方法演示:

public class MapDemo1 {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<Integer,String>();

        method(map);

    }

    private static void method(Map<Integer, String> map) {

        //添加
        System.out.println(map.put(8, "wangcai"));
        System.out.println(map.put(8, "xiaoqiang"));
        map.put(2, "zhangsan");
        map.put(4, "lisi");
        System.out.println(map);

        //删除
        System.out.println("remove:"+map.remove(2));

        //判断
        System.out.println("containskey:"+map.containsKey(7));

        //获取
        System.out.println("get:"+map.get(6));


    }

}

2、重点方法keySet

取出map中的所有元素。

原理:通过keySet方法取出map中的所有键所在的Set集合,再通过Set的迭代器获取每一个键,再通过map集合的get方法获取每个键所对应的值。

public class MapDemo2 {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<Integer,String>();

        method(map);

    }

    private static void method(Map<Integer, String> map) {

        map.put(2, "zhangsan");
        map.put(8, "lisi");
        map.put(7, "wangwu");
        map.put(6, "zhaoliu");

        Set<Integer> keySet = map.keySet();
        Iterator<Integer> it = keySet.iterator();

        while(it.hasNext()) {
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key+":"+value);
        }

    }

}

输出结果:
2:zhangsan
6:zhaoliu
7:wangwu
8:lisi

3、重点方法entrySet

该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.Entry类型(结婚证)。

public class MapDemo3 {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<Integer,String>();

        method(map);

    }

    private static void method(Map<Integer, String> map) {

        map.put(2, "zhangsan");
        map.put(8, "lisi");
        map.put(7, "wangwu");
        map.put(6, "zhaoliu");

        Set<Map.Entry<Integer,String>> entrySet = map.entrySet();

        Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();

        while(it.hasNext()) {
            Map.Entry<Integer, String> merryEntry = it.next();
            Integer key = merryEntry.getKey();
            String value = merryEntry.getValue();
            System.out.println(key+":"+value);
        }

    }

}

4、values方法

Collection values()

返回此映射中包含的值的Collection视图。

public class MapDemo4 {

    public static void main(String[] args) {

        Map<Integer,String> map = new HashMap<Integer,String>();

        method(map);

    }

    public static void method(Map<Integer, String> map) {
        map.put(2, "zhangsan");
        map.put(8, "lisi");
        map.put(7, "wangwu");
        map.put(6, "zhaoliu");

        Collection<String> values = map.values();

        Iterator<String> it = values.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }

}

5、Map集合-常见子类对象

Map常见子类:

|– Hashtable:

内部结构是哈希表,是同步的。不允许null作为键和值。

|—— Properties:

可以用来存储键值对型的配置文件的信息,可以和IO技术相结合。

|– HashMap:

内部结构是哈希表,不是同步的。允许null作为键和值。

|– TreeMap:

内部结构是二叉树,不是同步的。可以对Map集合中的键排序。

6、HashMap存储自定义对象

public class MapDemo5 {

    public static void main(String[] args) {

        /**
         * 将学生对象和学生的归属地通过键与值存储到map集合中。
         */

        HashMap<Student,String> hm = new HashMap<Student,String>();

        hm.put(new Student("zhangsan",20),"上海");
        hm.put(new Student("lisi",21),"北京");
        hm.put(new Student("wangwu",30),"临沂");
        hm.put(new Student("wangwu",30),"临沂");

        Set<Student> keySet = hm.keySet();

        Iterator<Student> it = keySet.iterator();

        while(it.hasNext()) {
            Student key = it.next();
            String value = hm.get(key);
            System.out.println(key.getName()+":"+key.getAge()+":"+value);
        }


    }

}

输出结果:
zhangsan:20:上海
wangwu:30:临沂
wangwu:30:临沂
lisi:21:北京

Student类继承自Person2类,通过在Person2类中覆盖重写hashCode和equals方法,去重,保证唯一性。

7、TreeMap存储自定义对象

public class MapDemo6 {

    public static void main(String[] args) {

        /**
         * 将学生对象和学生的归属地通过键与值存储到map集合中。
         * 按姓名排序
         */

        TreeMap<Student,String> tm = new TreeMap<Student,String>(new ComparatorByName());

        tm.put(new Student("zhangsan",20),"上海");
        tm.put(new Student("lisi",21),"北京");
        tm.put(new Student("wangwu",30),"临沂");
        tm.put(new Student("wangwu",30),"临沂");

        Set<Map.Entry<Student,String>> entrySet = tm.entrySet();

        Iterator<Map.Entry<Student, String>> it = entrySet.iterator();

        while(it.hasNext()) {
            Map.Entry<Student, String> merryEntry = it.next();
            Student key = merryEntry.getKey();
            String value = merryEntry.getValue();
            System.out.println(key.getName()+":"+key.getAge()+":"+value);
        }
    }

}

public class ComparatorByName implements Comparator<Person2> {

    @Override
    public int compare(Person2 o1, Person2 o2) {
        Person2 p1 = (Person2)o1;
        Person2 p2 = (Person2)o2;
        int temp = p1.getName().compareTo(p2.getName());
        return temp==0?p1.getAge()-p2.getAge():temp;
    }    

}

8、LinkedHashMap

public class MapDemo7 {

    public static void main(String[] args) {

        HashMap<Integer,String> hm = new LinkedHashMap<Integer,String>();

        hm.put(7, "aaaa");
        hm.put(2, "bbbb");
        hm.put(1, "dddd");
        hm.put(10, "ccc");

        Iterator<Map.Entry<Integer,String>> it = hm.entrySet().iterator();

        while(it.hasNext()) {
            Map.Entry<Integer, String> merryEntry = it.next();
            Integer key = merryEntry.getKey();
            String value = merryEntry.getValue();

            System.out.println(key+":"+value);
        }

    }

}

输出结果:
7:aaaa
2:bbbb
1:dddd
10:ccc

由HashMap变为LinkedHashMap之后,存和取的顺序保持了一致。

9、Map集合练习 - 按自然顺序,记录字母出现次数

public class MapDemp8 {


    public static void main(String[] args) {

        String str = "jslsjflAAsCCjl  ++js--lajaslasjfsala";

        String s = getCarCount(str);

        System.out.println(s);

    }

    private static String getCarCount(String str) {

        //字符串变字符数组
        char[] charArr = str.toCharArray();

        //TreeSet集合
        TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();

        for (int i = 0; i < charArr.length; i++) {

            if(!(charArr[i] >= 'a' && charArr[i] <= 'z' || charArr[i] >= 'A' && charArr[i] <= 'Z')) {
                continue;
            }

            Character chara = charArr[i];
            Integer val = tm.get(chara);
            if(val == null) {
                tm.put(chara, 1);
            }else {
                Integer count = tm.get(chara) + 1;
                tm.put(chara,count);
            }


        }

        return mapToString(tm);
    }

    private static String mapToString(TreeMap<Character, Integer> tm) {
        StringBuilder sb = new StringBuilder();

        Set<Character> keySet = tm.keySet();

        Iterator<Character> it = keySet.iterator();

        while(it.hasNext()) {
            Character key = it.next();
            Integer value = tm.get(key);
            sb.append(key+"("+value+")");
        }

        return sb.toString();
    }

}

输出结果:
A(2)C(2)a(5)f(2)j(6)l(6)s(7)

集合框架三 - 查阅技巧

三、集合框架-集合查阅的技巧

唯一性?

– 需要唯一:Set

—- 需要顺序?

—— 需要: TreeSet

—— 不需要: HashSet

—— 和存储一致的顺序:LinkedHashSet

– 不需要唯一:List

—- 频繁增删?

—– 需要:LinkedList

—— 不需要:ArrayList

结构体系:

List

|– ArrayList

|– LinkedList

Set

|– HashSet

|– TreeSet

后缀名就是该集合所属的体系。

前缀名就是该集合的数据结构。

看到array:就要想到数组,查询快,有角标。

看到Link:就要想到增删快,想到add get remove+first last的方法。

看到hash:就要想到hash表,唯一性,元素需要覆盖hashCode方法和equals方法。

看到tree:就要想到二叉树,排序,两个接口Compareble和Comparator。

而且这些常用的集合容器都是不同步的。

集合框架二 - 泛型

二、集合框架-泛型

public class GenericDemo {

    public static void main(String[] args) {
        ArrayList<String> al = new ArrayList<String>();

        al.add("abc");
        al.add("abc2");
        al.add("abc3");

        Iterator<String> it = al.iterator();
        while(it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }

    }

}

1、概述:

jdk1.5出现的安全机制。

好处:

1、将运行时期的问题ClassCastException转到了编译时期。

2、避免了强制转换的麻烦。

<>:什么时候用?当操作的引用类型不确定的时候,就使用<>。将要操作的引用数据类型传入即可。

其实<>就是一个用于接收具体引用数据类型的参数范围。

2、泛型-擦除&补偿

泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。

运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称之为泛型的擦除。

为什么擦除?是为了兼容运行的类加载器。

泛型的补偿:在运行时,通过获取元素的类型进行转换。不用使用者再强制转换了。

3、泛型在集合中的应用

public class GenericDemo2 {

    public static void main(String[] args) {
        TreeSet<Person2> ts = new TreeSet<Person2>();
        ts.add(new Person2("lisi8",21));
        ts.add(new Person2("lisi2",23));
        ts.add(new Person2("lisi",21));
        ts.add(new Person2("lis0",20));

        Iterator<Person2> it = ts.iterator();
        while(it.hasNext()) {
            Person2 p = it.next();
            System.out.println(p.getName()+":"+p.getAge());
        }

    }

}

public class Person2 implements Comparable<Person2> {
    private String name;
    private int age;

    public Person2() {
        super();
    }

    public Person2(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public int compareTo(Person2 p){
        int temp = this.age - p.getAge();
        return temp==0?this.name.compareTo(p.getName()):temp;    
    }

    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;
    }    

}

class CompareByname implements Comparator<Person2>{
    public int compare(Person2 o1, Person2 o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp == 0?o1.getAge() - o2.getAge():temp;    
    }
}

//按年龄排序,输出结果:
lis0:20
lisi:21
lisi8:21
lisi2:23

//按姓名排序,输出结果:
lis0:20
lisi:21
lisi2:23
lisi8:21

4、泛型类

在jdk1.5后,使用泛型来接收类中要操作的引用数据类型

什么时候用?当类中的操作的引用数据类型不确定的时候,就使用泛型来表示。
public class Student {

}

public class Worker {

}

public class Tool01<XX> {
    private XX q;

    public XX getObject() {
        return q;
    }
    public void setObject(XX object) {
        this.q = object;
    }
}

public class GenericDemo3 {
    public static void main(String[] args) {

        Tool01<Student> tool = new Tool01<Student>();
        tool.setObject(new Student());
        Student stu = tool.getObject();
        System.out.println(stu);

    }
}

当tool.setObject(new Student());传递Worker对象时tool.setObject(new Worker());编译就会报错。

5、泛型方法

class Tool02<XX> {//泛型定义在类上

    public void print(XX str) {
        System.out.println("print:"+str);
    }

    /**
     * 将泛型定义到方法上
     */
    public <W> void show(W str) {
        System.out.println("show:"+str);
    }

    /**
     * 当定义静态方法时,不能访问类上定义的泛型。静态方法只能将泛型定义到方法上才能使用泛型。
     */
    public static <Y> void output(Y str) {
        System.out.println("output:"+str);
    }
}

public class GenericDemo4 {

    public static void main(String[] args) {

        Tool02<String> tool = new Tool02<String>();

        //print方法只能使用生成对象时指定的String类型
        tool.print("abc");

        //泛型定义到了tool方法上,可以传递任意类型对象,编译都不会报错
        tool.show(new Integer(4));
        tool.show("abc");

        //静态方法的泛型只能定义到静态方法上可以传递任意类型对象
        Tool02.output("abc");
        Tool02.output(8);

    }

}    

6、泛型的接口

public class GenericDemo5 {

    public static void main(String[] args) {

        InterImpl in = new InterImpl();
        in.show("abc");

        InterImpl2<Integer> in2 = new InterImpl2<Integer>();
        in2.show(5);


    }

}

interface Inter<T>{
    public void show(T t);
}

class InterImpl implements Inter<String>{
    public void show(String str) {
        System.out.println("show:"+str);
    }
}

class InterImpl2<X> implements Inter<X>{
    public void show(X x) {
        System.out.println("show:"+x);
    }
}

7、泛型限定(上限)

泛型的通配符:?

代表未知类型

public class GenericDemp6 {

    public static void main(String[] args) {

        ArrayList<String> al = new ArrayList<String>();
        al.add("abc");
        al.add("ddd");

        ArrayList<String> al2 = new ArrayList<String>();
        al.add("abc2");
        al.add("ddd2");

        printCollection(al);
        printCollection(al2);

    }

    public static void printCollection(Collection<?> al) {
        Iterator<?> it = al.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }

    public static <X> void printCollection2(Collection<X> al) {
        Iterator<X> it = al.iterator();
        while(it.hasNext()) {
            X str = it.next();
            System.out.println(str);
        }
    }

}

? extends E 限定只能传E或者E的子类

public class Student extends Person2{

    public Student() {
        super();
    }

    public Student(String name, int age) {
        super(name, age);
    }

    public String toString() {
        return "student:"+getName()+":"+getAge();
    }

}

public class Worker extends Person2 {

    public Worker() {
        super();
    }

    public Worker(String name, int age) {
        super(name, age);
    }

    public String toString() {
        return "worker:"+getName()+":"+getAge();
    }
}

public class GenericDemo7 {

    public static void main(String[] args) {

        ArrayList<Worker> al = new ArrayList<Worker>();
        al.add(new Worker("worker01",30));
        al.add(new Worker("worker02",32));

        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("worker01",10));
        al2.add(new Student("worker02",11));

        printCollection(al);
        printCollection(al2);

    }

    //限定只能传Person2的对象或者Person2的子类对象
    private static void printCollection(ArrayList<? extends Person2> al) {

        Iterator<? extends Person2> it = al.iterator();

        while(it.hasNext()) {
            System.out.println(it.next().toString());
        }

    }

}

8、泛型限定(下限)

? super E 限定只能传E或者E的父类

public class GenericDemo7 {

    public static void main(String[] args) {

        ArrayList<Person2> al = new ArrayList<Person2>();
        al.add(new Person2("Person",30));
        al.add(new Person2("Person",32));

        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("worker01",10));
        al2.add(new Student("worker02",11));

        printCollection(al);
        printCollection(al2);

    }

    //限定只能传Student的对象或者父类Person2的对象,而不能传Worker对象
    private static void printCollection(ArrayList<? super Student> al) {

        Iterator<? super Student> it = al.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }

}

9、泛型限定-上限的体现

一般在存储元素时候都是用上限,因为这样取出的时都是按照上限类型来运算的。不会出现类型的安全隐患。

public class GenericDemo8 {

    public static void main(String[] args) {

        ArrayList<Person2> al = new ArrayList<Person2>();
        al.add(new Person2("Person",30));
        al.add(new Person2("Person",32));

        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("studnet01",10));
        al2.add(new Student("studnet02",11));

        ArrayList<Worker> al3 = new ArrayList<Worker>();
        al3.add(new Worker("worker01",20));
        al3.add(new Worker("worker02",21));

        al.addAll(al2);
        al.addAll(al3);

    }

}

class MyCollection<E>{
    public void add(E e) {

    }
    public void addAll(MyCollection<? extends E> e){

    }
}

10、泛型限定-下限的体现

通常对集合中的元素进行取出操作时,可以用下限。

public class GenericDemo9 {

    public static void main(String[] args) {

        TreeSet<Person2> al = new TreeSet<Person2>(new CompareByName2());
        al.add(new Person2("aaa",30));
        al.add(new Person2("bbb",32));
        al.add(new Person2("ccc",32));
        al.add(new Person2("ddd",34));

        TreeSet<Student> al2 = new TreeSet<Student>();
        al2.add(new Student("studnet01",10));
        al2.add(new Student("studnet02",11));

        al.addAll(al2);

        Iterator<Person2> it = al.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }

}

class CompareByName2 implements Comparator<Person2>{

    @Override
    public int compare(Person2 o1, Person2 o2) {
        int temp = o1.getName().compareTo(o2.getName());
        return temp == 0? o1.getAge() - o2.getAge():temp;
    }

}

集合框架一 - Collecion集合

集合框架的构成和分类

java中集合类的关系图

http://blog.csdn.net/real_neu/article/details/52821491

一、集合框架 - 概述

1、特点 :

  • 用于存储对象的容器。

  • 集合的长度可变。

  • 集合中不能存储基本数据类型值。

2、体系&共性功能

框架的顶层Collection接口:

1、添加

boolean add(Object obj)

boolean addAll(Collection coll);

2、删除

boolean remove(Object)
boolean removeAll(Collection coll)
void clear()

3、判断

boolean contains(Object obj)
boolean containsAll(Collection coll)
boolean isEmpty();

4、获取

int size();
Iterator iterator(): 取出元素的方式:迭代器

5、其它

boolean retainAll(Collection coll): 取交集
Object toArray(): 将集合转为数组

3、方法演示

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {

    public static void main(String[] args) {
        Collection coll = new ArrayList();
        //show(coll);

        Collection c1 = new ArrayList();
        Collection c2 = new ArrayList();
        show(c1,c2);
    }

    public static void show(Collection c1, Collection c2) {
        //给c1添加元素
        c1.add("abc1");
        c1.add("abc2");
        c1.add("abc3");
        c1.add("abc4");

        //给c2添加元素
        c2.add("abc2");
        c2.add("abc6");
        c2.add("abc7");

        System.out.println("c1:"+c1);
        System.out.println("c2:"+c2);

        //演示addAll
        c1.addAll(c2);
        System.out.println("c1:"+c1);

        //演示removeAll,将两个集合中的相同元素从调用removeAll的集合中删除
        //boolean b = c1.removeAll(c2);
        //System.out.println("removeAll:"+b);
        //System.out.println("c1:"+c1);

        //演示containsAll
        boolean c = c1.contains(c2);
        System.out.println("containsAll:"+c);

        //演示retainAll
        System.out.println("c1:"+c1);
        System.out.println("c2:"+c2);
        boolean d = c1.retainAll(c2);
        System.out.println(d);
        System.out.println("c1:"+c1);
    }

    public static void show(Collection coll) {
        //添加
        coll.add("abc1");
        coll.add("abc2");
        coll.add("abc3");
        System.out.println(coll);

        //删除,会改变集合的长度
        coll.remove("abc2");
        System.out.println(coll);

        //清空
        coll.clear();
        System.out.println(coll);

        //判断
        System.out.println(coll.contains("abc3"));
    }

}

4、迭代器

使用方法

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class IteratorDemo {

    public static void main(String[] args) {
        Collection coll = new ArrayList();
        coll.add("abc1");
        coll.add("abc2");
        coll.add("abc3");
        coll.add("abc4");
        System.out.println(coll);
        //调用集合中的迭代器方法,是为了获取集合中的迭代器对象
//        Iterator it = coll.iterator();
//        while(it.hasNext()) {
//            System.out.println(it.next());
//        }

        for(Iterator it = coll.iterator(); it.hasNext(); ) {
            System.out.println(it.next());
        }

    }

}

原理

Iterator iterator(): 取出元素的方式:迭代器

该对象必须依赖于具体容器,因为每一个容器的数据结构都不同。

所以该迭代器对象是在容器内部实现的。

对于使用容器者而言,具体的实现方式不重要,只要通过容器获取到实现的迭代器的对象即可,也就是iterator方法。

Iterator接口就是对所有的Collection容器进行元素取出的公共接口。

5、List和Set的特点

Collection

|--    List:有序(存入和取出的顺序一致),元素都有索引,元素可以重复。

|-- Set:元素不能重复。

List:特有的常见方法

1、添加

void add(index,element)
void add(index,collection)

2、删除

Object remove(index)

3、修改

Object set(index,element)

4、获取

Object get(index)
int indexOf(Object)
int lastIndexOf(object)
List subList(fromIndex,toIndex)

list集合是可以完成对元素的增删改查的。

方法演示

public class listDemo2 {

    public static void main(String[] args) {
        List list = new ArrayList();
        show(list);
    }

    private static void show(List list) {
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");

        Iterator it = list.iterator();
        while(it.hasNext()) {
            System.out.println("next:"+it.next());
        }

        //list特有的取出元素的方式,set只能通过迭代器方式取出元素
        for(int x=0; x<list.size(); x++) {
            System.out.println("get:"+list.get(x));
        }
    }

}

演示2

public class listDemo3 {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");

        Iterator it = list.iterator();
        while(it.hasNext()) {
            Object obj = it.next();
            if(obj.equals("abc2")) {
                list.add("abc9");
            }else {                
                System.out.println("next:"+obj);
            }            
        }

        System.out.println(it.next());
    }

}

执行时,抛出并发修改的异常。
Exception in thread "main"         
java.util.ConcurrentModificationException

原因:
Iterator it = list.iterator();迭代器检查list集合长度为3。
当list.add("abc9"),修改了集合长度时,迭代器不知道。

解决方案:使用Iterator接口的子接口listIterator来完成在迭代中对元素进修改。

public class listDemo3 {

    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");

        //获取列表迭代器对象,它可以实现在迭代过程中对元素的增删改查,注意只有list集合具备该迭代功能
        ListIterator it = list.listIterator();

        while(it.hasNext()) {
            Object obj = it.next();
            if(obj.equals("abc2")) {
                //it.add("abc9");
                it.set("abc9");
            }
        }

        System.out.println(list);

        while(it.hasPrevious()) {
            System.out.println("previous:"+it.previous());
        }

    }

}

6、List常用子类的特点

List:

|– Vector:内部是数组数据结构,是同步的。增删,查询都很慢。

|– ArrayList:内部是数组数据结构,是不同步的。替代了Vector。查询的速度快。

|– LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。

– addFirst()

– addLast()

– getFirst() 获取但不移除,如果链表为空,抛出NoSuchElement异常

– getLast()

– removeFirst() 获取并移除,如果链表为空,抛出NoSuchElement异常

– removeLast()

jdk1.6

– offerFirst()

– offerLast()

– peekFirst() 获取但不移除,如果链表为空,返回null

– peekLast()

– pollFirst() 获取并移除,如果链接为空,返回null

– pollLast()

/**
 * 请使用LinkedList来模拟一个堆栈或者队列数据结构
 * 堆栈:先进后出
 * 队列:先进先出
 */
public class linkedListDemo {
    public static void main(String[] args) {

        DuiLie dl = new DuiLie();
        dl.myAdd("abc1");
        dl.myAdd("abc2");
        dl.myAdd("abc3");
        dl.myAdd("abc4");

        while(!dl.isNull()) {
            System.out.println(dl.myGet());
        }
    }
}

class DuiLie{
    private LinkedList link;

    public DuiLie() {
        link = new LinkedList();
    }

    public void myAdd(Object obj) {
        link.addLast(obj);
    }

    public Object myGet() {
        return link.removeFirst();
    }

    public boolean isNull() {
        return link.isEmpty();
    }
}

7、ArrayList集合存储自定义对象

public class arrayListTest {

    public static void main(String[] args) {

        ArrayList al = new ArrayList();
        al.add(new Person("lisi1",21));
        al.add(new Person("lisi2",22));
        al.add(new Person("lisi3",23));
        al.add(new Person("lisi4",24));

        Iterator it = al.iterator();
        while(it.hasNext()) {
            //System.out.println(((Person) it.next()).getName());
            Person p = (Person) it.next();
            System.out.println(p.getName()+"--"+p.getAge());
        }

    }

}

class Person{
    private String name;
    private int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    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;
    }
}    

集合框架-HashSet集合

Set:元素不可以重复,是无序的。

Set接口中的方法和Collection一致。

|– HashSet:内部数据结构是Hash表,是不同步的。

|– TreeSet:

public static void main(String[] args) {
        HashSet hs = new HashSet();

        hs.add("aaa");
        hs.add("bbb");
        hs.add("ccc");
        hs.add("ddd");

        Iterator it = hs.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }

集合框架 - 哈希表

HashSet集合数据结构是哈希表,所以存储元素的时候,首先使用元素的hashCode方法来确定位置,如果位置相同,在通过元素的equals方法来确定内容是否相同。

class Person{

    ...

    public int hashCode() {
        //System.out.println(this);
        return name.hashCode()+age*27;
    }

    public boolean equals(Object obj) {
    if(this == obj)
            return true;

    if(!(obj instanceof Person))
        throw new ClassCastException("类型不对");

    Person p = (Person)obj;

    System.out.println(this.name+"..."+this.age+"...equals..."+p.name+"..."+p.age);

    return this.name.equals(p.name) && this.age == p.age;
}

    ...

}    

public class hashSetDemo2 {

    public static void main(String[] args) {

        HashSet hs = new HashSet();

        hs.add(new Person("lisi1",21));
        hs.add(new Person("lisi2",22));
        hs.add(new Person("lisi3",23));
        hs.add(new Person("lisi4",24));
        hs.add(new Person("lisi4",24));

        Iterator it = hs.iterator();

        while(it.hasNext()) {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"..."+p.getAge());
        }

    }

}

8、删除ArrayList集合中的重复元素

public class arrayListPractice {

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add("abc1");
        al.add("abc2");
        al.add("abc3");
        al.add("abc4");
        al.add("abc1");
        al.add("abc3");

        System.out.println(al);

        al = getSingleElement(al);

        System.out.println(al);
    }

    private static ArrayList getSingleElement(ArrayList al) {
        //1、定义临时容器
        ArrayList temp = new ArrayList();
        //2、迭代al集合
        Iterator it = al.iterator();
        while(it.hasNext()) {
            Object obj = it.next();
            //3、判断是否重复
            if(!(temp.contains(obj))) {
                temp.add(obj);
            }
        }
        return temp;
    }

}

输出结果:
[abc1, abc2, abc3, abc4, abc1, abc3]
[abc1, abc2, abc3, abc4]

换成自定义对象测试:

    public static void main(String[] args) {
        ArrayList al = new ArrayList();
        al.add();
        al.add("abc2");
        al.add("abc3");
        al.add("abc4");
        al.add("abc1");
        al.add("abc3");

        System.out.println(al);

        al = getSingleElement(al);

        System.out.println(al);
    }

输出结果:
[lisi1:21, lisi2:22, lisi3:23, lisi4:24, lisi2:22, lisi3:23]
[lisi1:21, lisi2:22, lisi3:23, lisi4:24, lisi2:22, lisi3:23]

原因分析:
contains方法是用的equals方法来比较两个元素是否相同。
equals方法是自定义类继承的object中的方法,所以比较的是对象的内存地址。

所以,要到Person类中对equals方法进行重写覆盖,就像String类对equals方法进行了重写一样,只要内容相同,即视为元素相同。

public boolean equals(Object obj) {
    if(this == obj)
            return true;

    if(!(obj instanceof Person))
        throw new ClassCastException("类型不对");

    Person p = (Person)obj;

    //System.out.println(this.name+"..."+this.age+"...equals..."+p.name+"..."+p.age);

    return this.name.equals(p.name) && this.age == p.age;
}

9、集合框架-LinkedHashSet集合

HashSet保证了唯一,但是无序。

LinkedHashSet用链表进行了扩展。

public static void main(String[] args) {
    HashSet hs = new LinkedHashSet();

    hs.add("abc2");
    hs.add("abc1");
    hs.add("abc3");
    hs.add("abc4");

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

输出结果:
abc2
abc1
abc3
abc4

保证了集合既有序且唯一。

10、集合框架 - TreeSet集合

TreeSet:可以对Set集合中的元素进行排序。是不同步的。

判断元素唯一性的方式:就是根据比较方法的返回结果是否为0,是0,就是相同元素,不存。

TreeSet对元素进行排序的方式一:

让元素自身具备比较功能,元素就需要实现Comparable接口,重写覆盖compareTo方法。

public static void main(String[] args) {
    TreeSet ts = new TreeSet();

    ts.add("abc");
    ts.add("aaa");
    ts.add("abbc");
    ts.add("acsw");

    Iterator it = ts.iterator();

    while(it.hasNext()) {
        System.out.println(it.next());
    }

}

输出结果:    
aaa
abbc
abc
acsw

String类已经实现了Comparable接口,重写了compareTo方法,所以添加时对元素进行了排序。自定义的类,需要按需求自定义排序方式。

class Person implements Comparable{
    ...
    //按年龄排序,年龄相同的按姓名排序
    public int compareTo(Object o) {
        Person p = (Person)o;
        int temp = this.age - p.age;
        return temp == 0?this.name.compareTo(p.name):temp;
    }
    ...
}

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();

        ts.add(new Person("zhangsan",28));
        ts.add(new Person("wangwu",21));
        ts.add(new Person("lisi",26));
        ts.add(new Person("zhaoliu",28));        

        Iterator it = ts.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }
}

输出结果:
wangwu:21
lisi:26
zhangsan:28
zhaoliu:28
TreeSet对元素进行排序的方式二:

让集合自身具备比较功能,自定义一个比较器类,实现Comparator接口,重写覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。

//创建比较器
public class ComparableDemo implements Comparator {

    public int compare(Object o1, Object o2) {
        Person p1 = (Person)o1;
        Person p2 = (Person)o2;
        //按名字排序,名字相同者按年龄排序
        int temp = p1.getName().compareTo(p2.getName());
        return temp==0?p1.getAge()-p2.getAge():temp;
    }

}

public class TreeSetDemo {

    public static void main(String[] args) {
        //创建集合时传入比较器
        TreeSet ts = new TreeSet(new ComparableDemo());

        ts.add(new Person("zhangsan",28));
        ts.add(new Person("wangwu",21));
        ts.add(new Person("lisi",26));
        ts.add(new Person("zhaoliu",28));        

        Iterator it = ts.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }

    }

}

输出结果:
lisi:26
wangwu:21
zhangsan:28
zhaoliu:28

集合比较器优先于元素比较器,且更为常用。

TreeSet集合练习-字符串长度排序

public class TreeSetPractice {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet();

        ts.add("aaa");
        ts.add("zzzz");
        ts.add("bhjan");
        ts.add("lsdds");
        ts.add("hahaj");

        Iterator it = ts.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }

}
输出结果:
aaa
bhjan
hahaj
lsdds
zzzz

String类元素默认的是自然排序,想要按字条串长度排序,只能通过修改集合
的比较器来实现。

class ComparatorByLength implements Comparator{
    public int compare(Object o1, Object o2) {
        String s1 = (String)o1;
        String s2 = (String)o2;
        int temp = s1.length() - s2.length();
        return temp==0?s1.compareTo(s2):temp;
    }
}

public class TreeSetPractice {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new ComparatorByLength());

        ...        
    }

}

基本数据类型包装类

1、为了方便操作基本数据类型值,将其封装成了对象,在对象中定义属性和行为,丰富了该数据的操作。

数据类型 包装类
byte Byte
short Short
int Integer
long Long
flot Float
double Double
char Character
boolean Boolean

2、基本数据类型和字符串之间的转换

基本类型–>字符串

(1)、基本类型数值+””

(2)、用String类中的静态方法valueOf(基本类型数值)

字符串–>基本类型

(1)、静态方法 parseInt, parseLong, parseBoolean。。。。

8种基本数据类型中,只有Character没有parse的用法。

(2)、如果字符串被Integer进行了对象的封装。可以使用别一个非静态方法intValue()将一个Integer对象转成基本数据类型值。

Integer i = new Integer("123");
System.out.println(i.intValue());

3、进制转换

十进制–>其它进制

//转二进制
System.out.println(Integer.toBinaryString(60));
System.out.println(Integer.toString(60,2));

//转八进制
System.out.println(Integer.toOctalString(60));
System.out.println(Integer.toString(60,8));

//转十六进制
System.out.println(Integer.toHexString(60));
System.out.println(Integer.toString(60,16));

其它进制–>十进制 parseInt(“string”, radix)

//二进制转十进制
System.out.println(Integer.parseInt("110",2));

//八进制转十进制
System.out.println(Integer.parseInt("74",8));

//十六进制转十进制
System.out.println(Integer.parseInt("3c",16));

4、自动装箱拆箱

Integer i = new Integer(4);
jdk1.4以后简写为Integer i = 4; //自动装箱

i = i + 6;
是i = new Integer(i.intValue()+6)的简写,自动拆箱。

5、小结

Integer a = new Integer(127);
Integer b = new Integer(127);

System.out.println(a==b);//fasle,对象比较地址
System.out.println(a.equals(b));//true,比较内容

Integer x = 129;
Integer y = 129;

System.out.println(x==y);//fasle
System.out.println(x.equals(y));//true

Integer x = 127;
Integer y = 127;

System.out.println(x==y);//true
System.out.println(x.equals(y));//true

x,y都为127时,x==y为true,都为129时,x==y为false

是因为jdk1.5以后,自动装箱时,如果装箱的在一个字节空间内(-128~127),那么该数据会被共享,不会重新开辟空间,因此都为127时,比较x==y时,实际上是一个地址。

6、练习

对字符串中的数值排序

import java.util.Arrays;

public class WrapperTest {
    private static final String SPACE_SEPARATOR = " ";

    public static void main(String[] args) {
        String numStr = "20 83 32     11 -7 50";
        System.out.println(numStr);
        numStr = sortStringNumber(numStr);
        System.out.println(numStr);
    }

    private static String sortStringNumber(String numStr) {
        //字符串变成字符串数组
        String[] str_arr = stringToArray(numStr);

        //字符串数组变成int数组
        int[] num_arr = toIntArray(str_arr);

        //int数组排序
        mySortArray(num_arr);

        //排序后的int数组变成字符串
        String temp = arrayToString(num_arr);

        return temp;
    }

    private static String arrayToString(int[] num_arr) {
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<num_arr.length; i++) {
            if(i!=num_arr.length-1)
                sb.append(num_arr[i]+SPACE_SEPARATOR);
            else
                sb.append(num_arr[i]);
        }
        return sb.toString();
    }

    private static void mySortArray(int[] num_arr) {
        Arrays.sort(num_arr);
    }

    private static int[] toIntArray(String[] str_arr) {
        int[] arr = new int[str_arr.length];
        for(int i=0; i<arr.length; i++) {
            arr[i] = Integer.parseInt(str_arr[i]);
        }
        return arr;
    }

    public static String[] stringToArray(String numStr) {
        String[] str_arr = numStr.split(SPACE_SEPARATOR+"+");
        return str_arr;
    }

}

常用对象API-StringBuffer类

StringBuffer就是字符串缓冲区,用于存储数据的容器,初始被容量16个字符。

1、特点

(1)、长度是可变的

(2)、可以存储不同类型的数据

(3)、最终转成字符串进行使用

(4)、可以对字符串进行插入修改

2、方法

(1)、添加 返回StringBuffer类型的对象

StringBuffer append(data)

StringBuffer sb = new StringBuffer();
sb.append(4);
sb.append(true);
sb.insert(1, false);
System.out.println(sb); //4falsetrue输出字符串

(2)、指定位置插入

insert(index, data) 

(3)、删除 返回StringBuffer类型的对象

StringBuffer delete(start, end),包含头,不包含尾

StringBuffer deleteCharAt(int index),删除指定位置元素

StringBuffer sb = new StringBuffer("abce");
sb.delete(1, 3);
System.out.println(sb);//ae

(4)、查找

char charAt(index);
int indexOf(stirng);
int lastIndexOf(string);

(5)、修改

StringBuffer replace(int start, int end, string str)

void setCharAt(index, char);    

sb.replace(1,3,"nba");//anbae

sb.setCharAt(2, '1');//abqe    

3、StringBuilder类

jdk1.5以后出现了功能和StringBuffer一样的对象。就是StringBuilder。

不同的是:

StringBuffer是线程同步的,通常用于多线程。

StringBuilder是线程不同步的,通常用于单线程,提高效率。

public class StringBuilderTest {

    public static void main(String[] args) {
        int[] arr = {3,1,5,1,2};
        String s = arrayToString(arr);
        System.out.println(s);
    }

    public static String arrayToString(int[] arr) {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for(int i= 0; i<arr.length; i++) {
            if(i!=arr.length - 1)
                sb.append(arr[i]+", ");
            else
                sb.append("]");
        }
        return sb.toString();
    }

    public static String arrayToString2(int[] arr)         {
        String str = "[";
        for(int i=0; i<arr.length; i++) {
            if(i!=arr.length - 1)
                str+=arr[i]+", ";
            else
                str+=arr[i]+"]";
        }
        return str;
    }
}

字符串拼接的方式会在字符串常量池中生成多个字符串。因此,推荐用缓冲区容器的方式。