diff --git a/core/lib/Drupal/Core/Config/Schema/Sequence.php b/core/lib/Drupal/Core/Config/Schema/Sequence.php
index bce81a9..e66e027 100644
--- a/core/lib/Drupal/Core/Config/Schema/Sequence.php
+++ b/core/lib/Drupal/Core/Config/Schema/Sequence.php
@@ -84,14 +84,31 @@ public function first() {
   /**
    * {@inheritdoc}
    */
-  public function set($index, $item) {
-    $this->offsetSet($index, $item);
+  public function set($index, $value) {
+    $this->offsetSet($index, $value);
     return $this;
   }
 
   /**
    * {@inheritdoc}
    */
+  public function removeItem($index) {
+    $this->offsetUnset($index);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appendItem($value = NULL) {
+    $offset = $this->count();
+    $this->offsetSet($offset, $value);
+    return $this->offsetGet($offset);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function filter($callback) {
     $this->value = array_filter($this->value, $callback);
     unset($this->elements);
diff --git a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
index 40a695e..6920bbb 100644
--- a/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
+++ b/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php
@@ -1077,7 +1077,7 @@ protected function mapToStorageRecord(ContentEntityInterface $entity, $table_nam
         // @todo Give field types more control over this behavior in
         //   https://drupal.org/node/2232427.
         if (!$definition->getMainPropertyName() && count($columns) == 1) {
-          $value = $entity->$field_name->first()->getValue();
+          $value = $entity->$field_name->isEmpty() ? array() : $entity->$field_name->first()->getValue();
         }
         else {
           $value = isset($entity->$field_name->$column_name) ? $entity->$field_name->$column_name : NULL;
@@ -1287,7 +1287,7 @@ protected function loadFieldItems(array $entities) {
             }
 
             // Add the item to the field values for the entity.
-            $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}[$delta_count[$row->entity_id][$row->langcode]] = $item;
+            $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}->appendItem($item);
             $delta_count[$row->entity_id][$row->langcode]++;
           }
         }
diff --git a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
index a96bdd4..c353be2 100644
--- a/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
+++ b/core/lib/Drupal/Core/Field/BaseFieldDefinition.php
@@ -463,9 +463,12 @@ public function setDefaultValue($value) {
    */
   public function getOptionsProvider($property_name, FieldableEntityInterface $entity) {
     // If the field item class implements the interface, proxy it through.
-    $item = $entity->get($this->getName())->first();
-    if ($item instanceof OptionsProviderInterface) {
-      return $item;
+    if (is_subclass_of($this->getFieldItemClass(), '\Drupal\Core\TypedData\OptionsProviderInterface')) {
+      $items = $entity->get($this->getName());
+      // If the field is empty, create an item so that we can use it as the
+      // "options provider".
+      // @todo we should clear it afterwards ?
+      return $items->first() ?: $items->appendItem();
     }
     // @todo: Allow setting custom options provider, see
     // https://www.drupal.org/node/2002138.
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 27305dc..be1cea3 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -46,11 +46,6 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
    */
   public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
     parent::__construct($definition, $name, $parent);
-    // Always initialize one empty item as most times a value for at least one
-    // item will be present. That way prototypes created by
-    // \Drupal\Core\TypedData\TypedDataManager::getPropertyInstance() will
-    // already have this field item ready for use after cloning.
-    $this->list[0] = $this->createItem(0);
   }
 
   /**
@@ -133,23 +128,27 @@ public function setValue($values, $notify = TRUE) {
         $values = array(0 => $values);
       }
 
-      // Clear the values of properties for which no value has been passed.
-      if (isset($this->list)) {
-        $this->list = array_intersect_key($this->list, $values);
-      }
-
-      // Set the values.
-      foreach ($values as $delta => $value) {
-        if (!is_numeric($delta)) {
+      // Non-numeric keys are not supported.
+      array_walk($values, function ($value, $index) {
+        if (!is_numeric($index)) {
           throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
         }
-        elseif (!isset($this->list[$delta])) {
+      });
+
+      // Assign incoming values. Keys are renumbered to ensure 0-based
+      // sequential deltas. If possible, reuse existing items rather than
+      // creating new ones.
+      foreach (array_values($values) as $delta => $value) {
+        if (!isset($this->list[$delta])) {
           $this->list[$delta] = $this->createItem($delta, $value);
         }
         else {
           $this->list[$delta]->setValue($value, FALSE);
         }
       }
+      // Truncate extraneous pre-existing values.
+      $this->list = array_slice($this->list, 0, count($values));
+
     }
     // Notify the parent of any changes.
     if ($notify && isset($this->parent)) {
@@ -161,28 +160,39 @@ public function setValue($values, $notify = TRUE) {
    * {@inheritdoc}
    */
   public function __get($property_name) {
-    return $this->first()->__get($property_name);
+    // For empty fields, $entity->field->property is NULL.
+    if ($item = $this->first()) {
+      return $item->__get($property_name);
+    }
   }
 
   /**
    * {@inheritdoc}
    */
   public function __set($property_name, $value) {
-    $this->first()->__set($property_name, $value);
+    // For empty fields, $entity->field->property = $value automatically
+    // creates the item before assigning the value.
+    $item = $this->first() ?: $this->appendItem();
+    $item->__set($property_name, $value);
   }
 
   /**
    * {@inheritdoc}
    */
   public function __isset($property_name) {
-    return $this->first()->__isset($property_name);
+    if ($item = $this->first()) {
+      return $item->__isset($property_name);
+    }
+    return FALSE;
   }
 
   /**
    * {@inheritdoc}
    */
   public function __unset($property_name) {
-    return $this->first()->__unset($property_name);
+    if ($item = $this->first()) {
+      $item->__unset($property_name);
+    }
   }
 
   /**
@@ -205,17 +215,18 @@ public function defaultAccess($operation = 'view', AccountInterface $account = N
    * {@inheritdoc}
    */
   public function applyDefaultValue($notify = TRUE) {
-    $value = $this->getFieldDefinition()->getDefaultValue($this->getEntity());
-
-    // NULL or array() mean "no default value", but  0, '0' and the empty string
-    // are valid default values.
-    if (!isset($value) || (is_array($value) && empty($value))) {
-      // Create one field item and apply defaults.
-      $this->first()->applyDefaultValue(FALSE);
-    }
-    else {
+    if ($value = $this->getFieldDefinition()->getDefaultValue($this->getEntity())) {
       $this->setValue($value, $notify);
     }
+    else {
+      // Create one field item and give it a chance to apply its defaults.
+      // Remove it if this ended up doing nothing...
+      // @todo Having to create an item in case it wants to set a value is
+      // absurd. Remove that in https://www.drupal.org/node/2356623.
+      $item = $this->first() ?: $this->appendItem();
+      $item->applyDefaultValue(FALSE);
+      $this->filterEmptyItems();
+    }
     return $this;
   }
 
diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index 4d3d666..68cfe2e 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -168,6 +168,11 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
     $elements = array();
 
     for ($delta = 0; $delta <= $max; $delta++) {
+      // Add a new empty item if it doesn't exist yet at this delta.
+      if (!isset($items[$delta])) {
+        $items->appendItem();
+      }
+
       // For multiple fields, title and description are handled by the wrapping
       // table.
       $element = array(
diff --git a/core/lib/Drupal/Core/TypedData/ListInterface.php b/core/lib/Drupal/Core/TypedData/ListInterface.php
index 09dce07..5c6cf99 100644
--- a/core/lib/Drupal/Core/TypedData/ListInterface.php
+++ b/core/lib/Drupal/Core/TypedData/ListInterface.php
@@ -58,16 +58,15 @@ public function get($index);
    *
    * @param int $index
    *   Index of the item to replace.
-   * @param mixed
-   *   Item to be stored at the specified position.
+   * @param mixed $value
+   *   The value of the item to be stored at the specified position.
    *
-   * @return static
-   *   Returns the list.
+   * @return $this
    *
    * @throws \Drupal\Core\TypedData\Exception\MissingDataException
    *   If the complex data structure is unset and no item can be set.
    */
-  public function set($index, $item);
+  public function set($index, $value);
 
   /**
    * Returns the first item in this list.
@@ -81,6 +80,27 @@ public function set($index, $item);
   public function first();
 
   /**
+   * Appends a new item to the list
+   *
+   * @param mixed $value
+   *   The value of the new item.
+   *
+   * @return \Drupal\Core\TypedData\TypedDataInterface
+   *   The item that was appended.
+   */
+  public function appendItem($value = NULL);
+
+  /**
+   * Removes the item at the specified position.
+   *
+   * @param int $index
+   *   Index of the item to remove.
+   *
+   * @return $this
+   */
+  public function removeItem($index);
+
+  /**
    * Filters the items in the list using a custom callback.
    *
    * @param callable $callback
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
index 7b110c4..2c7e3ed 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
@@ -61,27 +61,29 @@ public function setValue($values, $notify = TRUE) {
       $this->list = array();
     }
     else {
+      // Only arrays with numeric keys are supported.
       if (!is_array($values)) {
         throw new \InvalidArgumentException('Cannot set a list with a non-array value.');
       }
-
-      // Clear the values of properties for which no value has been passed.
-      if (isset($this->list)) {
-        $this->list = array_intersect_key($this->list, $values);
-      }
-
-      // Set the values.
-      foreach ($values as $delta => $value) {
-        if (!is_numeric($delta)) {
+      array_walk($values, function ($value, $index) {
+        if (!is_numeric($index)) {
           throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
         }
-        elseif (!isset($this->list[$delta])) {
+      });
+
+      // Assign incoming values. Keys are renumbered to ensure 0-based
+      // sequential deltas. If possible, reuse existing items rather than
+      // creating new ones.
+      foreach (array_values($values) as $delta => $value) {
+        if (!isset($this->list[$delta])) {
           $this->list[$delta] = $this->createItem($delta, $value);
         }
         else {
           $this->list[$delta]->setValue($value);
         }
       }
+      // Truncate extraneous pre-existing values.
+      $this->list = array_slice($this->list, 0, count($values));
     }
     // Notify the parent of any changes.
     if ($notify && isset($this->parent)) {
@@ -110,29 +112,61 @@ public function get($index) {
     if (!is_numeric($index)) {
       throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.');
     }
-    // Allow getting not yet existing items as well.
-    // @todo: Maybe add a public createItem() method in addition?
-    elseif (!isset($this->list[$index])) {
-      $this->list[$index] = $this->createItem($index);
+    // Automatically create the first item for "computed lists".
+// @todo what would be an example of "getItemDefinition()->isComputed()" ?
+    if ($index == 0 && !isset($this->list[0]) && ($this->definition->isComputed() || $this->definition->getItemDefinition()->isComputed())) {
+      $this->list[0] = $this->createItem(0);
     }
-    return $this->list[$index];
+    return isset($this->list[$index]) ? $this->list[$index] : NULL;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function set($index, $item) {
-    if (is_numeric($index)) {
-      // Support setting values via typed data objects.
-      if ($item instanceof TypedDataInterface) {
-        $item = $item->getValue();
-      }
-      $this->get($index)->setValue($item);
-      return $this;
-    }
-    else {
+  public function set($index, $value) {
+    if (!is_numeric($index)) {
       throw new \InvalidArgumentException('Unable to set a value with a non-numeric delta in a list.');
     }
+    if (!isset($this->list[$index])) {
+      throw new \InvalidArgumentException('Unable to set a value to a non-existent delta in a list.');
+    }
+    // Support setting values via typed data objects.
+    if ($value instanceof TypedDataInterface) {
+      $value = $value->getValue();
+    }
+    $this->list[$index]->setValue($value);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function removeItem($index) {
+    if (!is_numeric($index)) {
+      throw new \InvalidArgumentException('Unable to drop a non-numeric delta.');
+    }
+    if (isset($this->list) && array_key_exists($index, $this->list)) {
+      // Remove the item, and reassign deltas.
+      unset($this->list[$index]);
+      $this->rekey($index);
+    }
+    return $this;
+  }
+
+  /**
+   * @todo
+   *
+   * @param int $from_index
+   */
+  protected function rekey($from_index = 0) {
+    // Re-key the list to maintain consecutive indexes.
+    $this->list = array_values($this->list);
+    // Each item holds its own delta as a "name".
+    foreach ($this->list as $delta => $value) {
+      if ($delta >= $from_index) {
+        $value->setContext($delta, $this);
+      }
+    }
   }
 
   /**
@@ -146,16 +180,15 @@ public function first() {
    * Implements \ArrayAccess::offsetExists().
    */
   public function offsetExists($offset) {
-    return isset($this->list) && array_key_exists($offset, $this->list) && $this->get($offset)->getValue() !== NULL;
+    // We do not want to throw exceptions here, so we do not use get().
+    return isset($this->list[$offset]);
   }
 
   /**
    * Implements \ArrayAccess::offsetUnset().
    */
   public function offsetUnset($offset) {
-    if (isset($this->list)) {
-      unset($this->list[$offset]);
-    }
+    $this->removeItem($offset);
   }
 
   /**
@@ -166,6 +199,29 @@ public function offsetGet($offset) {
   }
 
   /**
+   * {@inheritdoc}
+   */
+  public function offsetSet($offset, $value) {
+    if (!isset($offset)) {
+      // The [] operator has been used.
+      $this->appendItem($value);
+    }
+    else {
+      $this->set($offset, $value);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appendItem($value = NULL) {
+    $offset = count($this->list);
+    $item = $this->createItem($offset, $value);
+    $this->list[$offset] = $item;
+    return $item;
+  }
+
+  /**
    * Helper for creating a list item object.
    *
    * @return \Drupal\Core\TypedData\TypedDataInterface
@@ -182,17 +238,6 @@ public function getItemDefinition() {
   }
 
   /**
-   * Implements \ArrayAccess::offsetSet().
-   */
-  public function offsetSet($offset, $value) {
-    if (!isset($offset)) {
-      // The [] operator has been used so point at a new entry.
-      $offset = $this->list ? max(array_keys($this->list)) + 1 : 0;
-    }
-    $this->set($offset, $value);
-  }
-
-  /**
    * Implements \IteratorAggregate::getIterator().
    */
   public function getIterator() {
@@ -245,12 +290,7 @@ public function filter($callback) {
         }
       });
       if ($removed) {
-        // Rekey the array using array_values().
-        $this->list = array_values($this->list);
-        // Manually update each item's delta.
-        foreach ($this->list as $delta => $item) {
-          $item->setContext($delta, $this);
-        }
+        $this->rekey();
       }
     }
     return $this;
diff --git a/core/modules/comment/src/CommentFieldItemList.php b/core/modules/comment/src/CommentFieldItemList.php
new file mode 100644
index 0000000..5c0297b
--- /dev/null
+++ b/core/modules/comment/src/CommentFieldItemList.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\comment\CommentFieldItemList.
+ */
+
+namespace Drupal\comment;
+
+use Drupal\Core\Field\FieldItemList;
+
+/**
+ * Defines a item list class for comment fields.
+ */
+class CommentFieldItemList extends FieldItemList {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($index) {
+    // The Field API only applies the "field default value" to newly created
+    // entities. In the specific case of the "comment status", though, we need
+    // this default value to be also applied for existing entities created
+    // before the comment field was added, which have no value stored for the
+    // field.
+    if ($index == 0 && empty($this->list)) {
+      $field_default_value = $this->getFieldDefinition()->getDefaultValue($this->getEntity());
+      return $this->appendItem($field_default_value[0]);
+    }
+    return parent::get($index);
+  }
+
+}
diff --git a/core/modules/comment/src/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/src/Plugin/Field/FieldType/CommentItem.php
index 93274a5..90811cc 100644
--- a/core/modules/comment/src/Plugin/Field/FieldType/CommentItem.php
+++ b/core/modules/comment/src/Plugin/Field/FieldType/CommentItem.php
@@ -22,6 +22,7 @@
  *   id = "comment",
  *   label = @Translation("Comments"),
  *   description = @Translation("This field manages configuration and presentation of comments on an entity."),
+ *   list_class = "\Drupal\comment\CommentFieldItemList",
  *   default_widget = "comment_default",
  *   default_formatter = "comment_default"
  * )
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php b/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php
index a343190..83b1ff8 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationSyncImageTest.php
@@ -154,7 +154,7 @@ function testImageFieldSync() {
         'alt' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
         'title' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
       );
-      $entity->{$this->fieldName}->get($delta)->setValue($item);
+      $entity->{$this->fieldName}[] = $item;
 
       // Store the generated values keying them by fid for easier lookup.
       $values[$default_langcode][$fid] = $item;
@@ -180,7 +180,7 @@ function testImageFieldSync() {
         'alt' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
         'title' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
       );
-      $translation->{$this->fieldName}->get($delta)->setValue($item);
+      $translation->{$this->fieldName}[] = $item;
 
       // Again store the generated values keying them by fid for easier lookup.
       $values[$langcode][$fid] = $item;
diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
index 4bf3196..26b7de2 100644
--- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php
+++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php
@@ -386,7 +386,7 @@ function testDefaultValue() {
 
     // Create a new node to check that datetime field default value is not set.
     $new_node = entity_create('node', array('type' => 'date_content'));
-    $this->assertNull($new_node->get($field_name)->offsetGet(0)->value, 'Default value is not set');
+    $this->assertNull($new_node->get($field_name)->value, 'Default value is not set');
   }
 
   /**
diff --git a/core/modules/datetime/src/Tests/DateTimeItemTest.php b/core/modules/datetime/src/Tests/DateTimeItemTest.php
index d83d2a2..465326a 100644
--- a/core/modules/datetime/src/Tests/DateTimeItemTest.php
+++ b/core/modules/datetime/src/Tests/DateTimeItemTest.php
@@ -114,7 +114,7 @@ public function testSetValueProperty() {
     $entity = entity_create('entity_test');
     $value = '2014-01-01T20:00:00Z';
 
-    $entity->set('field_datetime', $value);
+    $entity->field_datetime->value = $value;
     $entity->save();
     // Load the entity and ensure the field was saved correctly.
     $id = $entity->id();
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceFormatterTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceFormatterTest.php
index 8b8edca..16c3d5b 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceFormatterTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceFormatterTest.php
@@ -247,15 +247,18 @@ protected function buildRenderArray(array $referenced_entities, $formatter, $for
     // Create the entity that will have the entity reference field.
     $referencing_entity = entity_create($this->entityType, array('name' => $this->randomMachineName()));
 
-    $delta = 0;
+    $items = $referencing_entity->get($this->fieldName);
     foreach ($referenced_entities as $referenced_entity) {
-      $referencing_entity->{$this->fieldName}[$delta]->entity = $referenced_entity;
-      $referencing_entity->{$this->fieldName}[$delta++]->access = TRUE;
+      // @todo Using the $items[] = array(...) syntax fails to populate the
+      //   item's target_id, which causes $items->referencedEntity() to return
+      //   incorrect results. Switch to the simpler syntax after
+      //   https://www.drupal.org/node/2386559 is fixed.
+      $item = $items->appendItem();
+      $item->entity = $referenced_entity;
+      $item->access = TRUE;
     }
 
     // Build the renderable array for the entity reference field.
-    $items = $referencing_entity->get($this->fieldName);
-
     return $items->view(array('type' => $formatter, 'settings' => $formatter_options));
   }
 
diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php
index 9ae0fc4..99dfe86 100644
--- a/core/modules/field/src/Entity/FieldStorageConfig.php
+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -600,9 +600,12 @@ public function isRequired() {
    */
   public function getOptionsProvider($property_name, FieldableEntityInterface $entity) {
     // If the field item class implements the interface, proxy it through.
-    $item = $entity->get($this->getName())->first();
-    if ($item instanceof OptionsProviderInterface) {
-      return $item;
+    if (is_subclass_of($this->getFieldItemClass(), '\Drupal\Core\TypedData\OptionsProviderInterface')) {
+      $items = $entity->get($this->getName());
+      // If the field is empty, create an item so that we can use it as the
+      // "options provider".
+      // @todo we should clear it afterwards ?
+      return $items->first() ?: $items->appendItem();
     }
     // @todo: Allow setting custom options provider, see
     // https://www.drupal.org/node/2002138.
diff --git a/core/modules/field/src/Tests/FieldDataCountTest.php b/core/modules/field/src/Tests/FieldDataCountTest.php
index 1930c27..2a14652 100644
--- a/core/modules/field/src/Tests/FieldDataCountTest.php
+++ b/core/modules/field/src/Tests/FieldDataCountTest.php
@@ -72,11 +72,9 @@ public function testEntityCountAndHasData() {
     // Create 12 entities to ensure that the purging works as expected.
     for ($i=0; $i < 12; $i++) {
       $entity = entity_create('entity_test');
-      $value = mt_rand(1,99);
-      $value2 = mt_rand(1,99);
-      $entity->field_int[0]->value = $value;
-      $entity->field_int[1]->value = $value2;
-      $entity->name->value = $this->randomMachineName();
+      $entity->field_int[] = mt_rand(1,99);
+      $entity->field_int[] = mt_rand(1,99);
+      $entity->name[] = $this->randomMachineName();
       $entity->save();
     }
 
diff --git a/core/modules/field/src/Tests/FieldStorageCrudTest.php b/core/modules/field/src/Tests/FieldStorageCrudTest.php
index c72e63d..cf68ecc 100644
--- a/core/modules/field/src/Tests/FieldStorageCrudTest.php
+++ b/core/modules/field/src/Tests/FieldStorageCrudTest.php
@@ -399,7 +399,7 @@ function testUpdate() {
       // Fill in the entity with more values than $cardinality.
       for ($i = 0; $i < 20; $i++) {
         // We can not use $i here because 0 values are filtered out.
-        $entity->field_update[$i]->value = $i + 1;
+        $entity->field_update[] = $i + 1;
       }
       // Load back and assert there are $cardinality number of values.
       $entity = $this->entitySaveReload($entity);
diff --git a/core/modules/field/src/Tests/FieldValidationTest.php b/core/modules/field/src/Tests/FieldValidationTest.php
index 4454c23..71bb8ad 100644
--- a/core/modules/field/src/Tests/FieldValidationTest.php
+++ b/core/modules/field/src/Tests/FieldValidationTest.php
@@ -52,7 +52,7 @@ function testCardinalityConstraint() {
     $entity = $this->entity;
 
     for ($delta = 0; $delta < $cardinality + 1; $delta++) {
-      $entity->{$this->fieldTestData->field_name}->get($delta)->set('value', 1);
+      $entity->{$this->fieldTestData->field_name}[] = array('value' => 1);
     }
 
     // Validate the field.
@@ -85,7 +85,7 @@ function testFieldConstraints() {
         $value = -1;
         $expected_violations[$delta . '.value'][] = t('%name does not accept the value -1.', array('%name' => $this->fieldTestData->field->getLabel()));
       }
-      $entity->{$this->fieldTestData->field_name}->get($delta)->set('value', $value);
+      $entity->{$this->fieldTestData->field_name}[] = $value;
     }
 
     // Validate the field.
diff --git a/core/modules/field_ui/src/Form/FieldEditForm.php b/core/modules/field_ui/src/Form/FieldEditForm.php
index 8de533c..82e34e9 100644
--- a/core/modules/field_ui/src/Form/FieldEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldEditForm.php
@@ -86,6 +86,7 @@ public function buildForm(array $form, FormStateInterface $form_state, FieldConf
     $ids = (object) array('entity_type' => $this->field->entity_type, 'bundle' => $this->field->bundle, 'entity_id' => NULL);
     $form['#entity'] = _field_create_entity_from_ids($ids);
     $items = $form['#entity']->get($this->field->getName());
+    $item = $items->first() ?: $items->appendItem();
 
     if (!empty($field_storage->locked)) {
       $form['locked'] = array(
@@ -140,7 +141,7 @@ public function buildForm(array $form, FormStateInterface $form_state, FieldConf
 
     // Add field settings for the field type and a container for third party
     // settings that modules can add to via hook_form_FORM_ID_alter().
-    $form['field']['settings'] = $items[0]->fieldSettingsForm($form, $form_state);
+    $form['field']['settings'] = $item->fieldSettingsForm($form, $form_state);
     $form['field']['settings']['#weight'] = 10;
     $form['field']['third_party_settings'] = array();
     $form['field']['third_party_settings']['#weight'] = 11;
diff --git a/core/modules/field_ui/src/Form/FieldStorageEditForm.php b/core/modules/field_ui/src/Form/FieldStorageEditForm.php
index 5cd57b7..557ffc8 100644
--- a/core/modules/field_ui/src/Form/FieldStorageEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldStorageEditForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\field_ui\Form;
 
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -108,7 +109,9 @@ public function buildForm(array $form, FormStateInterface $form_state, FieldConf
     // FieldItem.
     $ids = (object) array('entity_type' => $this->field->entity_type, 'bundle' => $this->field->bundle, 'entity_id' => NULL);
     $entity = _field_create_entity_from_ids($ids);
-    $form['field_storage']['settings'] += $entity->get($field_storage->getName())->first()->storageSettingsForm($form, $form_state, $field_storage->hasData());
+    $items = $entity->get($field_storage->getName());
+    $item = $items->first() ?: $items->appendItem();
+    $form['field_storage']['settings'] += $item->storageSettingsForm($form, $form_state, $field_storage->hasData());
 
     // Build the configurable field values.
     $cardinality = $field_storage->getCardinality();
diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
index d5a3e3d..b98fc33 100644
--- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -139,6 +139,8 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
     // Add one more empty row for new uploads except when this is a programmed
     // multiple form as it is not necessary.
     if ($empty_single_allowed || $empty_multiple_allowed) {
+      // Create a new empty item.
+      $items->appendItem();
       $element = array(
         '#title' => $title,
         '#description' => $description,
diff --git a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
index 8ae74de..e7919f7 100644
--- a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
+++ b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php
@@ -182,20 +182,16 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
     // Iterate through remaining items in data array. These should all
     // correspond to fields.
     foreach ($data as $field_name => $field_data) {
+      $items = $entity->get($field_name);
       // Remove any values that were set as a part of entity creation (e.g
-      // uuid). If this field is set to an empty array in the data, this will
-      // also have the effect of marking the field for deletion in REST module.
-      $entity->{$field_name} = array();
-
-      $field = $entity->get($field_name);
-      // Get the class of the field. This will generally be the default Field
-      // class.
-      $field_class = get_class($field);
-      // Pass in the empty field object as a target instance. Since the context
-      // is already prepared for the field, any data added to it is
-      // automatically added to the entity.
-      $context['target_instance'] = $field;
-      $this->serializer->denormalize($field_data, $field_class, $format, $context);
+      // uuid). If the incoming field data is set to an empty array, this will
+      // also have the effect of emptying the field in REST module.
+      $items->setValue(array());
+      if ($field_data) {
+        // Denormalize the field data into the FieldItemList object.
+        $context['target_instance'] = $items;
+        $this->serializer->denormalize($field_data, get_class($items), $format, $context);
+      }
     }
 
     return $entity;
diff --git a/core/modules/hal/src/Normalizer/FieldItemNormalizer.php b/core/modules/hal/src/Normalizer/FieldItemNormalizer.php
index a427fee..b437c1d 100644
--- a/core/modules/hal/src/Normalizer/FieldItemNormalizer.php
+++ b/core/modules/hal/src/Normalizer/FieldItemNormalizer.php
@@ -99,20 +99,17 @@ protected function constructValue($data, $context) {
    * @return \Drupal\Core\Field\FieldItemInterface
    *   The translated field item instance.
    */
-  protected function createTranslatedInstance(FieldItemInterface $field_item, $langcode) {
-    $field_items = $field_item->getParent();
+  protected function createTranslatedInstance(FieldItemInterface $item, $langcode) {
+    // Remove the untranslated item that was created for the default language
+    // by FieldNormalizer::denormalize().
+    $items = $item->getParent();
+    $delta = $item->getName();
+    unset($items[$delta]);
 
-    // Remove the untranslated instance from the field's list of items.
-    $field_items->offsetUnset($field_item->getName());
-
-    // Get the entity in the requested language and the field's item list from
-    // that.
-    $entity_translation = $field_item->getEntity()->getTranslation($langcode);
-    $field_items_translation = $entity_translation->get($field_item->getFieldDefinition()->getName());
-
-    // Create a new instance and return it.
-    $count = $field_items_translation->isEmpty() ? 0 : $field_items_translation->count();
-    return $field_items_translation->get($count);
+    // instead, create a new item for the entity in the requested language.
+    $entity_translation = $item->getEntity()->getTranslation($langcode);
+    $field_name = $item->getFieldDefinition()->getName();
+    return $entity_translation->get($field_name)->appendItem();
   }
 
 }
diff --git a/core/modules/hal/src/Normalizer/FieldNormalizer.php b/core/modules/hal/src/Normalizer/FieldNormalizer.php
index fd2851b..e93f226 100644
--- a/core/modules/hal/src/Normalizer/FieldNormalizer.php
+++ b/core/modules/hal/src/Normalizer/FieldNormalizer.php
@@ -68,19 +68,18 @@ public function denormalize($data, $class, $format = NULL, array $context = arra
       throw new InvalidArgumentException('The field passed in via $context[\'target_instance\'] must have a parent set.');
     }
 
-    $field = $context['target_instance'];
-    foreach ($data as $field_item_data) {
-      $count = $field->count();
-      // Get the next field item instance. The offset will serve as the field
-      // item name.
-      $field_item = $field->get($count);
-      $field_item_class = get_class($field_item);
-      // Pass in the empty field item object as the target instance.
-      $context['target_instance'] = $field_item;
-      $this->serializer->denormalize($field_item_data, $field_item_class, $format, $context);
+    $items = $context['target_instance'];
+    $item_class = $items->getItemDefinition()->getClass();
+    foreach ($data as $item_data) {
+      // Create a new item and pass it as the target for the unserialization of
+      // $item_data. Note: if $item_data is about a different language than the
+      // default, FieldItemNormalizer::denormalize() will dismiss this item and
+      // create a new one for the right language.
+      $context['target_instance'] = $items->appendItem();
+      $this->serializer->denormalize($item_data, $item_class, $format, $context);
     }
 
-    return $field;
+    return $items;
 
   }
 
diff --git a/core/modules/hal/src/Tests/DenormalizeTest.php b/core/modules/hal/src/Tests/DenormalizeTest.php
index 8b5711c..0310b2a 100644
--- a/core/modules/hal/src/Tests/DenormalizeTest.php
+++ b/core/modules/hal/src/Tests/DenormalizeTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\hal\Tests;
 
+use Drupal\field\Entity\FieldConfig;
 use Symfony\Component\Serializer\Exception\UnexpectedValueException;
 
 /**
@@ -78,20 +79,30 @@ public function testTypeHandling() {
   }
 
   /**
-   * Test that a field set to an empty array is different than an empty field.
+   * Test that a field set to an empty array is different than an absent field.
    */
   public function testMarkFieldForDeletion() {
-    $no_field_data = array(
+    // Add a default value for a field.
+    $field = FieldConfig::loadByName('entity_test', 'entity_test', 'field_test_text');
+    $field->default_value = array(array('value' => 'Llama'));
+    $field->save();
+
+    // Denormalize data that contains no entry for the field, and check that
+    // the default value is present in the resulting entity.
+    $data = array(
       '_links' => array(
         'type' => array(
           'href' => _url('rest/type/entity_test/entity_test', array('absolute' => TRUE)),
         ),
       ),
     );
-    $no_field_denormalized = $this->serializer->denormalize($no_field_data, $this->entityClass, $this->format);
-    $no_field_value = $no_field_denormalized->field_test_text->getValue();
+    $entity = $this->serializer->denormalize($data, $this->entityClass, $this->format);
+    $this->assertEqual($entity->field_test_text->count(), 1);
+    $this->assertEqual($entity->field_test_text->value, 'Llama');
 
-    $empty_field_data = array(
+    // Denormalize data that contains an empty entry for the field, and check
+    // that the field is empty in the resulting entity.
+    $data = array(
       '_links' => array(
         'type' => array(
           'href' => _url('rest/type/entity_test/entity_test', array('absolute' => TRUE)),
@@ -99,10 +110,8 @@ public function testMarkFieldForDeletion() {
       ),
       'field_test_text' => array(),
     );
-    $empty_field_denormalized = $this->serializer->denormalize($empty_field_data, $this->entityClass, $this->format);
-    $empty_field_value = $empty_field_denormalized->field_test_text->getValue();
-
-    $this->assertTrue(!empty($no_field_value) && empty($empty_field_value), 'A field set to an empty array in the data is structured differently than an empty field.');
+    $entity = $this->serializer->denormalize($data, get_class($entity), $this->format, [ 'target_instance' => $entity ]);
+    $this->assertEqual($entity->field_test_text->count(), 0);
   }
 
   /**
diff --git a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
index 9b44af0..e0f9df5 100644
--- a/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
+++ b/core/modules/menu_link_content/src/Entity/MenuLinkContent.php
@@ -79,7 +79,8 @@ public function getRouteName() {
    * {@inheritdoc}
    */
   public function getRouteParameters() {
-    return $this->get('route_parameters')->first()->getValue();
+    $item = $this->get('route_parameters')->first();
+    return $item ? $item->getValue() : array();
   }
 
   /**
@@ -128,7 +129,8 @@ public function getMenuName() {
    * {@inheritdoc}
    */
   public function getOptions() {
-    return $this->get('options')->first()->getValue();
+    $item = $this->get('options')->first();
+    return $item ? $item->getValue() : array();
   }
 
   /**
diff --git a/core/modules/node/src/Tests/NodeAccessLanguageAwareCombinationTest.php b/core/modules/node/src/Tests/NodeAccessLanguageAwareCombinationTest.php
index f73ac3b..dbb696c 100644
--- a/core/modules/node/src/Tests/NodeAccessLanguageAwareCombinationTest.php
+++ b/core/modules/node/src/Tests/NodeAccessLanguageAwareCombinationTest.php
@@ -110,7 +110,7 @@ protected function setUp() {
       'private' => FALSE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 0;
+    $translation->field_private->value = 0;
     $node->save();
 
     $this->nodes['private_both_public'] = $node = $this->drupalCreateNode(array(
@@ -120,7 +120,7 @@ protected function setUp() {
       'private' => TRUE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 0;
+    $translation->field_private->value = 0;
     $node->save();
 
     $this->nodes['public_hu_private'] = $node = $this->drupalCreateNode(array(
@@ -130,7 +130,7 @@ protected function setUp() {
       'private' => FALSE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 0;
+    $translation->field_private->value = 0;
     $node->save();
 
     $this->nodes['public_ca_private'] = $node = $this->drupalCreateNode(array(
@@ -140,7 +140,7 @@ protected function setUp() {
       'private' => FALSE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 1;
+    $translation->field_private->value = 1;
     $node->save();
 
     $this->nodes['public_both_private'] = $node = $this->drupalCreateNode(array(
@@ -150,7 +150,7 @@ protected function setUp() {
       'private' => FALSE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 1;
+    $translation->field_private->value = 1;
     $node->save();
 
     $this->nodes['private_both_private'] = $node = $this->drupalCreateNode(array(
@@ -160,7 +160,7 @@ protected function setUp() {
       'private' => TRUE,
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 1;
+    $translation->field_private->value = 1;
     $node->save();
 
     $this->nodes['public_no_language_private'] = $this->drupalCreateNode(array(
diff --git a/core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php b/core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php
index ad82dea..bb33f9c 100644
--- a/core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php
+++ b/core/modules/node/src/Tests/NodeAccessLanguageAwareTest.php
@@ -97,7 +97,7 @@ protected function setUp() {
       'field_private' => array(array('value' => 0)),
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 0;
+    $translation->field_private->value = 0;
     $node->save();
 
     $this->nodes['ca_private'] = $node = $this->drupalCreateNode(array(
@@ -106,7 +106,7 @@ protected function setUp() {
       'field_private' => array(array('value' => 0)),
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 1;
+    $translation->field_private->value = 1;
     $node->save();
 
     $this->nodes['hu_private'] = $node = $this->drupalCreateNode(array(
@@ -115,7 +115,7 @@ protected function setUp() {
       'field_private' => array(array('value' => 1)),
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 0;
+    $translation->field_private->value = 0;
     $node->save();
 
     $this->nodes['both_private'] = $node = $this->drupalCreateNode(array(
@@ -124,7 +124,7 @@ protected function setUp() {
       'field_private' => array(array('value' => 1)),
     ));
     $translation = $node->getTranslation('ca');
-    $translation->field_private[0]->value = 1;
+    $translation->field_private->value = 1;
     $node->save();
 
     $this->nodes['no_language_public'] = $this->drupalCreateNode(array(
diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php
index 770406a..e0422ff 100644
--- a/core/modules/shortcut/src/Entity/Shortcut.php
+++ b/core/modules/shortcut/src/Entity/Shortcut.php
@@ -108,7 +108,8 @@ public function setRouteName($route_name) {
    * {@inheritdoc}
    */
   public function getRouteParameters() {
-    return $this->get('route_parameters')->first()->getValue();
+    $item = $this->get('route_parameters')->first();
+    return $item ? $item->getValue() : array();
   }
 
   /**
diff --git a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
index dffdd48..480f3f2 100644
--- a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
@@ -70,8 +70,8 @@ public function testShortcutLinkAdd() {
       if (strpos($entity->route_name->value, 'node.') === 0) {
         $entity->save();
         $loaded = Shortcut::load($entity->id());
-        $this->assertEqual($entity->route_name->value, $loaded->route_name->value);
-        $this->assertEqual($entity->get('route_parameters')->first()->getValue(), $loaded->get('route_parameters')->first()->getValue());
+        $this->assertEqual($entity->getRouteName(), $loaded->getRouteName());
+        $this->assertEqual($entity->getRouteParameters(), $loaded->getRouteParameters());
       }
     }
 
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php b/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
index d315cb9..e4ba68e 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldDefaultValueTest.php
@@ -9,7 +9,6 @@
 
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Component\Utility\String;
-use Drupal\Core\Language\LanguageInterface;
 
 /**
  * Tests default values for entity fields.
@@ -51,7 +50,7 @@ protected function assertDefaultValues($entity_type) {
     $entity = entity_create($entity_type);
     $this->assertEqual($entity->langcode->value, 'en', String::format('%entity_type: Default language', array('%entity_type' => $entity_type)));
     $this->assertTrue(Uuid::isValid($entity->uuid->value), String::format('%entity_type: Default UUID', array('%entity_type' => $entity_type)));
-    $this->assertEqual($entity->name->getValue(), array(0 => array('value' => NULL)), 'Field has one empty value by default.');
+    $this->assertEqual($entity->name->getValue(), array(), 'Field has no empty value by default.');
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Entity/EntityFieldTest.php b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
index 41dbb44..f5643a0 100644
--- a/core/modules/system/src/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityFieldTest.php
@@ -243,20 +243,22 @@ protected function doTestReadWrite($entity_type) {
 
     // Tests adding a value to a field item list.
     $entity->name[] = 'Another name';
-    $this->assertEqual($entity->name[1]->value, 'Another name', format_string('%entity_type: List item added via [].', array('%entity_type' => $entity_type)));
-    $entity->name[2]->value = 'Third name';
-    $this->assertEqual($entity->name[2]->value, 'Third name', format_string('%entity_type: List item added by a accessing not yet created item.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name[1]->value, 'Another name', format_string('%entity_type: List item added via [] and the first property.', array('%entity_type' => $entity_type)));
+    $entity->name[] = array('value' => 'Third name');
+    $this->assertEqual($entity->name[2]->value, 'Third name', format_string('%entity_type: List item added via [] and an array of properties.', array('%entity_type' => $entity_type)));
 
     // Test removing and empty-ing list items.
     $this->assertEqual(count($entity->name), 3, format_string('%entity_type: List has 3 items.', array('%entity_type' => $entity_type)));
     unset($entity->name[1]);
     $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Second list item has been removed.', array('%entity_type' => $entity_type)));
-    $entity->name[2] = NULL;
+    $this->assertEqual($entity->name[1]->value, 'Third name', format_string('%entity_type: The subsequent items have been shifted up.', array('%entity_type' => $entity_type)));
+    $this->assertEqual($entity->name[1]->getName(), 1, format_string('%entity_type: The items names have been updated to their new delta.', array('%entity_type' => $entity_type)));
+    $entity->name[1] = NULL;
     $this->assertEqual(count($entity->name), 2, format_string('%entity_type: Assigning NULL does not reduce array count.', array('%entity_type' => $entity_type)));
-    $this->assertTrue($entity->name[2]->isEmpty(), format_string('%entity_type: Assigning NULL empties the item.', array('%entity_type' => $entity_type)));
+    $this->assertTrue($entity->name[1]->isEmpty(), format_string('%entity_type: Assigning NULL empties the item.', array('%entity_type' => $entity_type)));
 
     // Test using isEmpty().
-    unset($entity->name[2]);
+    unset($entity->name[1]);
     $this->assertFalse($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is not empty.', array('%entity_type' => $entity_type)));
     $entity->name->value = NULL;
     $this->assertTrue($entity->name[0]->isEmpty(), format_string('%entity_type: Name item is empty.', array('%entity_type' => $entity_type)));
@@ -628,8 +630,7 @@ public function testEntityConstraintValidation() {
       ->setLabel('Test entity')
       ->setSetting('target_type', 'entity_test');
     $reference_field = \Drupal::typedDataManager()->create($definition);
-    $reference = $reference_field->first()->get('entity');
-    $reference->setValue($entity);
+    $reference = $reference_field->appendItem(array('entity' => $entity))->get('entity');
 
     // Test validation the typed data object.
     $violations = $reference->validate();
@@ -656,8 +657,7 @@ public function testEntityConstraintValidation() {
         'target_bundle' => 'article',
       ));
     $reference_field = \Drupal::TypedDataManager()->create($definition);
-    $reference = $reference_field->first()->get('entity');
-    $reference->setValue($node);
+    $reference = $reference_field->appendItem(array('entity' => $node))->get('entity');
     $violations = $reference->validate();
     $this->assertEqual($violations->count(), 1);
 
diff --git a/core/modules/system/src/Tests/TypedData/TypedDataTest.php b/core/modules/system/src/Tests/TypedData/TypedDataTest.php
index 99032f4..ecb3c37 100644
--- a/core/modules/system/src/Tests/TypedData/TypedDataTest.php
+++ b/core/modules/system/src/Tests/TypedData/TypedDataTest.php
@@ -331,11 +331,9 @@ public function testTypedDataLists() {
 
     // Test using array access.
     $this->assertEqual($typed_data[0]->getValue(), 'one');
-    $typed_data[4] = 'four';
-    $this->assertEqual($typed_data[4]->getValue(), 'four');
-    $typed_data[] = 'five';
-    $this->assertEqual($typed_data[5]->getValue(), 'five');
-    $this->assertEqual($typed_data->count(), 5);
+    $typed_data[] = 'four';
+    $this->assertEqual($typed_data[3]->getValue(), 'four');
+    $this->assertEqual($typed_data->count(), 4);
     $this->assertTrue(isset($typed_data[0]));
     $this->assertTrue(!isset($typed_data[6]));
 
@@ -366,13 +364,14 @@ public function testTypedDataLists() {
 
     $this->assertEqual($typed_data->getValue(), array(NULL, '', 'three'));
     // Test unsetting.
-    unset($typed_data[2]);
+    unset($typed_data[1]);
     $this->assertEqual(count($typed_data), 2);
-    $this->assertNull($typed_data[3]->getValue());
+    // Check that items were shifted.
+    $this->assertEqual($typed_data[1]->getValue(), 'three');
 
-    // Getting a not set list item sets it.
-    $this->assertNull($typed_data[4]->getValue());
-    $this->assertEqual(count($typed_data), 4);
+    // Getting a not set list item returns NULL, and does not create a new item.
+    $this->assertNull($typed_data[2]);
+    $this->assertEqual(count($typed_data), 2);
 
     // Test setting the list with less values.
     $typed_data->setValue(array('one'));
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 3e7cb73..fc78f57 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -323,11 +323,13 @@ function entity_test_entity_test_insert($entity) {
 function entity_test_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
   if ($field_definition->getName() == 'field_test_text') {
     if ($items) {
-      if ($items[0]->value == 'no access value') {
-        return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
+      if ($items->value == 'no access value') {
+        return AccessResult::forbidden()
+          ->cacheUntilEntityChanges($items->getEntity());
       }
-      elseif ($operation == 'delete' && $items[0]->value == 'no delete access value') {
-        return AccessResult::forbidden()->cacheUntilEntityChanges($items->getEntity());
+      elseif ($operation == 'delete' && $items->value == 'no delete access value') {
+        return AccessResult::forbidden()
+          ->cacheUntilEntityChanges($items->getEntity());
       }
     }
   }
@@ -341,7 +343,7 @@ function entity_test_entity_field_access($operation, FieldDefinitionInterface $f
  * @see \Drupal\system\Tests\Entity\FieldAccessTest::testFieldAccess()
  */
 function entity_test_entity_field_access_alter(array &$grants, array $context) {
-  if ($context['field_definition']->getName() == 'field_test_text' && $context['items'][0]->value == 'access alter value') {
+  if ($context['field_definition']->getName() == 'field_test_text' && $context['items']->value == 'access alter value') {
     $grants[':default'] = AccessResult::forbidden()->inheritCacheability($grants[':default'])->cacheUntilEntityChanges($context['items']->getEntity());
   }
 }
