集合框架

Java中集合类的关系图
(虚线框是接口 实线框是类)

图片.png

一、集合

集合:就是用于存储对象地址的。

集合的特点
1.用于存储对象的容器。
2.集合的长度是可变的。
3.集合中不可以存储基本数据类型值。

数组和集合的区别
数组和集合都可以存对象
数组是固定长度的,可以存储基本数据类型值
集合是可变长度的,不可以存储基本数据类型值

二、集合框架

集合容器因为内部的数据结构不同,有多种具体容器。
不断向上抽取,就形成了集合框架。

集合框架的顶层Collection接口

Collection的常见方法:

  • 1.添加

    • 添加一个:
      boolean add(E e);
      E其实就是object

    • 添加一些:
      boolean addAll(Collection coll);

  • 2.删除

    • 删除一个:
      boolean remove(Object o);

    • 删除一些:
      boolean removeAll(Collection coll);

    • 删除全部(将集合中所有元素都删除)
      void clear();

  • 3.判断

    • 判断collection是否包含指定的元素
      boolean contains(object obj);

    • 判断collection是否包含指定的一些元素
      boolean containsAll(Collection coll);

    • 判断集合是否为空
      boolean isEmpty();

  • 4.获取

    • 获取长度
      int size();

    • 获取集合元素——迭代器
      Iterator iterator();
      Iterator:迭代器对象

  • 5.其他

    • 取交集
      boolean retainAll(Collection coll);

    • 将集合转成数组
      Object[] toArray();

方法演示1
方法演示2
方法演示3
方法演示4
方法演示5

三、Iterator(迭代器)

迭代器的使用

取出集合中元素的方式

获取集合中的迭代器对象

迭代器原理
该对象必须依赖于具体容器,因为每个容器的数据结构不同。所以该迭代器对象是在容器中进行内部实现的。
(迭代器是实现Iterator接口的每一个容器内部的内部对象)
对于使用容器者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器对象即可。也就是Iterator方法。
Iterator接口就是对所有的Collection容器进行元素取出的公共接口。

四、List(列表)

是Collection接口的子接口

特点

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

特有的常见方法

List的共性特点就是都可以操作角标。
List元素可以完成对元素的增删改查!

  • 添加

    • 向列表尾部添加指定元素
      boolean add(Object obj);
    • 在列表的指定位置插入指定元素
      void add(index,element);
    • 添加指定 collection 中的所有元素到此列表的结尾
      boolean addAll(Collection c);
    • 添加指定 collection 中的所有元素都插入到列表中的指定位置
      boolean addAll(index,collection);
  • 删除

    • 移除列表中指定位置的元素,返回那个被删的元素
      Object remove(index);
  • 修改

    • 用指定元素替换列表中指定位置的元素
      Object set(index,element);
  • 获取

    • 获取列表中指定元素
      Object get(index);
    • 获取此列表中第一次出现的指定元素的索引
      int indexOf(object);
    • 获取此列表中最后出现的指定元素的索引
      int lastIndexOf(object);
    • 获取子列表
      fromIndex(包括 )和 toIndex(不包括)之间的元素
      List subList(fromIndex,toIndex);
添加演示
删除演示
修改演示
获取演示

List特有获取元素方式:

获取所有元素演示

ListIterator

使用迭代器,在迭代过程中,不能用集合的方式去添加元素(会出现异常),而迭代器本身又没有添加的方法,所以就有了ListIterator(列表迭代器)。
ListIterator是迭代器(Iterator)下的子接口

举个栗子啦

其中boolean hasNext();是正向遍历列表
boolean hasPreviours();是逆向遍历列表

List常用子类

  • Vector
    内部是数组数据结构,
    具有List的所有功能,
    但是是同步的,也就是说是安全的
    效率低
    增删查询都很慢

  • ArrayList(数组列表)
    内部是数组数据结构,
    是不同步的
    效率高
    替代了Vector
    查询的速度快

举个栗子:
定义功能去除ArrayList中的重复元素

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

/*
 * 定义功能去除ArrayList中的重复元素
 * 
 * */
public class HashSetDemo {
    public static void main(String[] args){
        ArrayList a1 = new ArrayList();
        a1.add("abc1");
        a1.add("abc2");
        a1.add("abc2");
        a1.add("abc1");
        a1.add("abc");
        System.out.println(a1);
        
        a1 = getSingleElement(a1);
        
        System.out.println(a1);
    }
    public static ArrayList getSingleElement(ArrayList a1) {
        //1.定义一个临时容器
        ArrayList temp = new ArrayList();
        //2.迭代a1集合
        Iterator it = a1.iterator();
        while(it.hasNext())
        {
            Object obj = it.next();
        //3.判断被迭代到的元素是否在临时容器中存在
            if(!temp.contains(obj))
            {
                temp.add(obj);
            }
        }
        return temp;
    }
}
运行结果
  • LinkedList(链式列表)
    内部是链表数据结构,
    是不同步的
    增删元素效率高

五、Set(集)

是Collection接口的子接口

特点

  • 无序:元素不能重复。

set接口中的方法和collection的方法一样

Set常用子类

  • HashSet(哈希表)
    内部数据结构是哈希表
    是不同步的
    不保证迭代顺序
    哈希是一种算法,算出来的值,存起来就是哈希表
演示

自定义哈希算法
1.哈希表确定元素是否相同
a)判断的是两个元素的哈希值是否相同
如果相同,再判断两个对象的内容是否相同。
b)判断哈希值相同,其实判断的是对象的hashCode的方法。
判断内容相同,用的是equals方法

如果哈希值不同,就不需要判断equals。

  • LinkedHashSet 类

具有可预知迭代顺序的set接口的哈希表和链接列表实现。
保证唯一且有序

有序的
  • TreeSet
    对Set集合中的元素进行排序
    元素唯一,判断方式就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
    不同步
TreeSet演示

1.TreeSet对元素进行排序的方式

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

2.TreeSet——二叉树
按照二叉树原则比较
比较的是返回值
左小右大
不能重复

Comparable接口
对象之间要进行比较,就实现这个接口
强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

Comparator接口(比较器)
强行对某个对象 collection 进行整体排序 的比较函数。

方法

  • 用来比较两个参数
    int compare(Object arg0, Object arg1);

举个栗子:
以Person对象年龄(姓名)进行从小到大的排序

先建一个Person类

//要进行对象比较,所以Person类实现comparable接口。
public class Person implements Comparable {
    
    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;
    }
    @Override
    public int compareTo(Object o) {
        Person p = (Person)o;
        
    /*      //按年龄比较
        int temp = this.age-p.age;
        return temp==0?this.name.compareTo(p.name):temp;   */
        //根据姓名比较
                int temp = this.name.compareTo(p.name);
        return temp==0?this.age-p.age:temp;
        
    }
    
}

再建一个TreeSet类进行排序

import java.util.Iterator;
import java.util.TreeSet;

import admin.Person;

public class TreeSetDemo {

    public static void main(String[] args) {
        TreeSet t = new TreeSet();
        t.add(new Person("zhangsan",22));
        t.add(new Person("wangwu",28));
        t.add(new Person("zhaosi",23));
        t.add(new Person("wangyu",27));
        
        
        Iterator it = t.iterator();
        
        while(it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"年龄:"+p.getAge());
        }
        
    }

}
按年龄排序
按姓名排序

上述方法用的是Person类中本身具备的比较方法
再用比较器对其进行排序

构建一个根据姓名比较的比较器类

import java.util.Comparator;
import admin.Person;

public class ComparatorByName implements Comparator {

    @Override
    public int compare(Object arg0, Object arg1) {

        Person p1 = (Person)arg0;//强转
        Person p2 = (Person)arg1;
        
        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 t = new TreeSet(new ComparatorByName());
        t.add(new Person("zhangsan",22));
        t.add(new Person("wangwu",28));
        t.add(new Person("zhaosi",23));
        t.add(new Person("wangyu",27));
        
        
        Iterator it = t.iterator();
        
        while(it.hasNext())
        {
            Person p = (Person)it.next();
            System.out.println(p.getName()+"年龄:"+p.getAge());
        }
        
    }

}
用比较器按姓名排序

当两种情况都存在,按照比较器排序。
比较器更为常用

再吃一个小栗子

对字符串进行长度排序

import java.util.Iterator;
import java.util.TreeSet;

import Comparator.ComparatorBylength;

/*
 * 对字符串进行长度排序
 * 
 * 思路
 * 1.TreeSet本身具有自然排序
 * 2.但需要的是字符串长度排序
 * 3.建一个构造器!
 * */
public class TreeSetPractise {

    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new ComparatorBylength());
        
        ts.add("aaaa");
        ts.add("asg");
        ts.add("df");
        ts.add("gtty");
        ts.add("akdjahds");
        
        Iterator it = ts.iterator();
        
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }

}

构建一个根据字符串长度比较的比较器类

import java.util.Comparator;

public class ComparatorBylength implements Comparator {

    @Override
    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;
        //compareTo是字符串自身具备的方法
    }

}

运行结果

六、Map集合

1.Map集合和Collection集合的区别
Map集合:一次添加一对元素;Map集合也称为双列集合。
Collection集合:一次添加一个元素;Collection集合也称为单列集合

2.Map<K,V>接口
K:key,键
V:value,值

也就是说Map集合中存储的是键值对。
Map中必须保证键的唯一性。
一个映射不能包含重复的键;每个键最多只能映射到一个值。
映射就是给一个对象(可以是变量、物体、等等)起一个唯一的别名。

3.常见方法

  • 添加
    value put(key,value);
    返回前一个和key关联的值,如果没有返回null。

  • 删除

    • 清空Map集合。
      void clear();
    • 根据指定的key删除这个键值对。
      value remove(key);
  • 判断

    • 判断是否包含键。
      boolean containsKey(key);
    • 判断是否包含值。
      boolean containsValue(value);
    • 判断是否有键值对。
      boolean isEmpty();
  • 获取

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

演示:

import java.util.HashMap;
import java.util.Map;

public class MapDemo {

    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap();
        method(map);
    }
public static void method(Map<Integer,String> map){
    //<Integer,String>泛型(学号,姓名)
    //添加
    System.out.println(map.put(8, "wangcai"));
    System.out.println(map.put(8, "xiaofang"));
    //存相同键,值会覆盖。
    map.put(2, "lele");
    map.put(5, "feifei");
    System.out.println(map);//打印集合
    
    //删除
    System.out.println("remove:"+map.remove(2));
    System.out.println(map);//打印集合
    //格式:键=值
    
    //判断
    System.out.println("containskey:"+map.containsKey(7));
    System.out.println(map);//打印集合

    //获取
    System.out.println("get:"+map.get(8));
    System.out.println("get:"+map.get(6));//不存在返回值为null
    System.out.println(map);//打印集合
}
}

运行结果:

运行结果

上述获取元素只能获取一个,但想要获取所有元素,就要用到keySet();

Set keySet()
返回此映射中包含的键的 Set 视图。

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

举个栗子:
代码:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo {

    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap();
        method_2(map);
    }
public static void method_2(Map<Integer,String> map){

    map.put(2, "lulu");
    map.put(3, "lele");
    map.put(4, "feifei");
    map.put(6, "yuanyuan");
    map.put(9, "baibai");
    
    //取出map中的所有元素。
    //原理:通过keySet方法获取map中所有的键所在的Set集合,再通过Set的迭代器获取
    //再对每一个键通过map集合的get方法获取其对应的值即可。
    
    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);
    }
}
}

运行结果:


运行结果

画个图更好的理解keySet()

图示keySet()

Set entrySet()
返回此映射中包含的映射关系的 Set 视图。

原理:通过Map转成set就可以迭代
该方法将键和值的映射关系作为对象存储到了Set集合中
根据Iterator迭代器通过Map.Entry对象的getKey,getValue获取其中的键和值。
这个映射关系的类型就是Map.Entry类型

代码:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo {

    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap();
//      method(map);
//      method_keySet(map);
        method_entrySet(map);
    }
public static void method_entrySet(Map<Integer,String> map){
    map.put(2, "lulu");
    map.put(3, "lele");
    map.put(4, "feifei");
    map.put(6, "yuanyuan");
    map.put(9, "baibai");
    
    /*原理:通过Map转成set就可以迭代
    该方法将键和值的映射关系作为对象存储到了Set集合中
    这个映射关系的类型就是Map.Entry类型*/
    
    Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
    Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
    while(it.hasNext()){
        Map.Entry<Integer,String> ma = it.next();
        Integer key = ma.getKey();
        String value = ma.getValue();
        System.out.println(key+":::"+value);
    }
}
}

运行结果:


运行结果

Collection<V> values();
返回此映射中包含的值的 Collection 视图。

只获取value的值不要key
代码:

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class MapDemo {

    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap();
        method_values(map);
    }
public static void method_values(Map<Integer,String> map){
    map.put(2, "lulu");
    map.put(3, "lele");
    map.put(4, "feifei");
    map.put(6, "yuanyuan");
    map.put(9, "baibai");
    
    //只获取value的值
    Collection<String> values = map.values();
    
    Iterator<String> it = values.iterator();
    while(it.hasNext()){
        System.out.println(it.next());
    }
}
}

运行结果:


运行结果

3.Map常用的子类

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

    • Properties类
      这个类表示了一个持久的属性集。
      用来存储键值对型的配置文件信息,可以和IO技术相结合。
  • HashMap
    内部结构是哈希表
    不同步
    允许null作为键,null作为值

HashMap存储自定义对象

举个栗子:
将学生对象和学生的归属地通过键与值存储到map集合中。
HashMapDemo代码如下:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import admin.Student;

public class HashMapDemo {

    public static void main(String[] args) {
        HashMap<Student,String> hm = new HashMap<Student,String>();
        
        hm.put(new Student("lisi",21),"北京");
        hm.put(new Student("wangwu",34),"上海");
        hm.put(new Student("zhangsan",19),"大连");
        hm.put(new Student("zhaoliu",25),"西安");
        hm.put(new Student("lisi",21),"沈阳");
        
            /* Set<Student> keySet = hm.keySet();
        Iterator<Student> it = keySet.iterator();    */
                //上面两句等价于下面这句
                Iterator<Student> it = hm.keySet().iterator();
        
        while(it.hasNext()){
            Student key = it.next();
            String value = hm.get(key);
            System.out.println(key.getName()+":"+key.getAge()+"----"+value);
        }
    }

}

Studen类代码:

public class Student extends Person {

    public Student() {
        super();
    }

    public Student(String name, int age) {
        super(name, age);
    }
    @Override
    public String toString(){
        return "student:"+getName()+":"+getAge();
    }
}

运行结果:

运行结果
  • TreeMap
    内部结构是二叉树
    不同步
    可以对Map集合中的键进行排序

TreeMap存储自定义对象

举个栗子:
TreeMapDemo类代码:

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import admin.Student;
import comparator.ComparatorByName;

public class TreeMapDemo {

    public static void main(String[] args) {
        
        TreeMap<Student,String> tm = new TreeMap<Student,String>(new ComparatorByName());
        
        tm.put(new Student("lisi",21),"北京");
        tm.put(new Student("wangwu",34),"上海");
        tm.put(new Student("zhangsan",19),"大连");
        tm.put(new Student("zhaoliu",25),"西安");
        tm.put(new Student("lisi",21),"沈阳");
        
        /*Set<Student> keySet = tm.keySet();
        
        Iterator<Student> it = keySet.iterator();*/
        
        Iterator<Map.Entry<Student,String>> it = tm.entrySet().iterator();
        
        while(it.hasNext()){
            Map.Entry<Student, String> me = it.next();
            Student key = me.getKey();
            String value = me.getValue();
            System.out.println(key.getName()+":"+key.getAge()+"----"+value);
        }
    }

}

ComparatorByName类比较器代码:

import java.util.Comparator;

import admin.Person;


public class ComparatorByName implements Comparator {

    @Override
    public int compare(Object arg0, Object arg1) {

        Person p1 = (Person)arg0;//强转
        Person p2 = (Person)arg1;
        
        int temp = p1.getName().compareTo(p2.getName());
        return temp==0?p1.getAge()-p2.getAge():temp;
    }

}

运行结果(按姓名排过序的):

运行结果
  • LinkedHashMap
    由于HashMap是按照Hash自己的排序方式存放的有序,但是当想取出来的时候就会不好找,用LinkedHashMap存放,好取好找。

举个栗子:

代码
运行结果

举一个Map集合的大栗子

获取字符串中,每个字母的出现次数
"fdgadhajskhslkha"
要求打印结果为:a(2)b(1)……

代码如下:

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/*
 * 获取字符串中,每个字母的出现次数
 *"fdgadhajskhslkha"
 *要求打印结果为:a(2)b(1)……
 *
 *思路:
 *1.由打印结果得出字母和次数之间存在这映射关系。
 *2.这种映射关系很多,所以需要存储
 *3.能存储映射关系的容器有数组和Map集合
 *4.数组有编号,集合没有
 *5.打印结果关系不需要有序编号
 *6.使用Map集合
 *7.但打印字母有排序
 *8.可以使用TreeMap集合
 *9.集合中应该存储的是字母和次数的对应关系
 *10.将字符串的字母变成字符数组
 *11.遍历字符数组,用字母作为键去查Map集合这个表
 *12.如果该字母键不存在,就将这个字母作为键1作为值存储在Map集合中
 *    如果该字母键存在,就将字母的键对应值取出并+1,再将该字母和+1后的值存储到map集合中
 *   键相同值会覆盖,这样就记录了改字母的次数
 *13.遍历结束,map集合就记录了所有字母出现的次数
 */

public class MapPractice {

    public static void main(String[] args) {
        
        String str = "fdgadhajskhslkha";
        String s = getCharCount(str);
        System.out.println(s);
    }
    //获取字符个数
    public static String getCharCount(String str) {
        
        //将字符串变成字符串数组
        char[] cha = str.toCharArray();
        //定义map集合表
        Map<Character,Integer> map = new TreeMap<Character,Integer>();
        
        for (int i = 0; i < cha.length; i++) {
            //将数组中的字母作为键去查map表
            Integer value = map.get(cha[i]);
            
            //判断值是否为null
            int count = 0;
            if(value!=null){
                count = value;
            }
            count++;
            map.put(cha[i], count);
            /*if(value==null){
                map.put(cha[i], 1);
            }else{
                map.put(cha[i], value+1);
            }*/
            
            
        }
        return mapToString(map);
    }
    private static String mapToString(Map<Character, Integer> map) {
        
        StringBuilder sb = new StringBuilder();
        Iterator<Character> it = map.keySet().iterator();
        
        while(it.hasNext()){
            Character key = it.next();
            Integer value = map.get(key);
            
            sb.append(key+"("+value+")");
        }
        
        return sb.toString();
    }

}

运行结果:

运行结果

七、集合查阅技巧

使用集合的判断技巧:

1.判断是否需要唯一:
需要:set ——>转2
不需要:List ——>转3
2.判断是否需要制定顺序:
需要:TreeSet
不需要:HashSet
需要一个和存储一致的顺序(有序):LinkedHashSet
3.判断是否需要频繁增删:
需要:LinkedList
不需要:ArrayList

记录容器结构和所属体系

1.List
ArrayList
LinkedList

2.Set
HashSet
TreeSet

后缀名就是该集合所属体系。
前缀名就是该集合的数据结构。

array:就能想到是数组,而且查询快,有角标。
link:就能想到链表,也就是说增删快。
hash:就能想到哈希表,还有唯一性,元素需要覆盖hashcode方法和equal方法。
Tree:就能想到二叉树,也就说能排序,就能想到有两个接口 Comparable,Comparator

而且常用的集合都是不同步的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342