diff --git a/core/modules/user/lib/Drupal/user/Controller/UserAdmin.php b/core/modules/user/lib/Drupal/user/Controller/UserAdmin.php
deleted file mode 100644
index c5da47753957b6b14d7e2d9ad1e23135712c9182..0000000000000000000000000000000000000000
--- a/core/modules/user/lib/Drupal/user/Controller/UserAdmin.php
+++ /dev/null
@@ -1,162 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Controller\UserAdmin.
- */
-
-namespace Drupal\user\Controller;
-
-use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\Query\QueryInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\user\UserStorageControllerInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides a user administrative listing.
- *
- * @todo Convert this to a entity list controller once table sort is supported.
- */
-class UserAdmin extends ControllerBase implements ContainerInjectionInterface {
-
-  /**
-   * The database connection.
-   *
-   * @var \Drupal\Core\Database\Connection
-   */
-  protected $connection;
-
-  /**
-   * The module handler.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * The user storage controller.
-   *
-   * @var \Drupal\user\UserStorageControllerInterface
-   */
-  protected $storageController;
-
-  /**
-   * The entity query.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryInterface
-   */
-  protected $entityQuery;
-
-  /**
-   * Constructs a new UserAdmin object.
-   *
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler.
-   * @param \Drupal\user\UserStorageControllerInterface $storage_controller
-   *   The user storage controller.
-   * @param \Drupal\Core\Entity\Query\QueryInterface $entity_query
-   *   The entity query.
-   */
-  public function __construct(Connection $connection, ModuleHandlerInterface $module_handler, UserStorageControllerInterface $storage_controller, QueryInterface $entity_query) {
-    $this->connection = $connection;
-    $this->moduleHandler = $module_handler;
-    $this->storageController = $storage_controller;
-    $this->entityQuery = $entity_query;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('database'),
-      $container->get('module_handler'),
-      $container->get('entity.manager')->getStorageController('user'),
-      $container->get('entity.query')->get('user')
-    );
-  }
-
-  /**
-   * User administrative listing.
-   *
-   * @return array
-   *   A render array as expected by drupal_render().
-   */
-  public function userList() {
-    $header = array(
-      'username' => array('data' => $this->t('Username'), 'field' => 'name', 'specifier' => 'name'),
-      'status' => array('data' => $this->t('Status'), 'field' => 'status', 'specifier' => 'status', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-      'roles' => array('data' => $this->t('Roles'), 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-      'member_for' => array('data' => $this->t('Member for'), 'field' => 'created', 'specifier' => 'created', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-      'access' => array('data' => $this->t('Last access'), 'field' => 'access', 'specifier' => 'access', 'class' => array(RESPONSIVE_PRIORITY_LOW)),
-      'operations' => $this->t('Operations'),
-    );
-
-    $this->entityQuery->condition('uid', 0, '<>');
-    $this->entityQuery->pager(50);
-    $this->entityQuery->tableSort($header);
-    $uids = $this->entityQuery->execute();
-    $accounts = $this->storageController->loadMultiple($uids);
-
-    $destination = drupal_get_destination();
-    $status = array($this->t('blocked'), $this->t('active'));
-    $roles = array_map('\Drupal\Component\Utility\String::checkPlain', user_role_names(TRUE));
-    unset($roles[DRUPAL_AUTHENTICATED_RID]);
-    $options = array();
-    foreach ($accounts as $account) {
-      $users_roles = array();
-      foreach ($account->getRoles() as $role) {
-        if (isset($roles[$role])) {
-          $users_roles[] = $roles[$role];
-        }
-      }
-      asort($users_roles);
-      $options[$account->id()]['username']['data'] = array(
-        '#theme' => 'username',
-        '#account' => $account,
-      );
-      $options[$account->id()]['status'] = $status[$account->isActive()];
-      $options[$account->id()]['roles']['data'] = array(
-        '#theme' => 'item_list',
-        '#items' => $users_roles,
-      );
-      $options[$account->id()]['member_for'] = format_interval(REQUEST_TIME - $account->getCreatedTime());
-      $options[$account->id()]['access'] = $account->access ? $this->t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->getLastAccessedTime()))) : t('never');
-      $links = array();
-      $links['edit'] = array(
-        'title' => $this->t('Edit'),
-        'href' => 'user/' . $account->id() . '/edit',
-        'query' => $destination,
-      );
-      if ($this->moduleHandler->invoke('content_translation', 'translate_access', array($account))) {
-        $links['translate'] = array(
-          'title' => $this->t('Translate'),
-          'href' => 'user/' . $account->id() . '/translations',
-          'query' => $destination,
-        );
-      }
-      $options[$account->id()]['operations']['data'] = array(
-        '#type' => 'operations',
-        '#links' => $links,
-      );
-    }
-
-    $build['accounts'] = array(
-      '#theme' => 'table',
-      '#header' => $header,
-      '#rows' => $options,
-      '#empty' => $this->t('No people available.'),
-    );
-    $build['pager'] = array(
-      '#theme' =>'pager',
-    );
-
-    return $build;
-  }
-
-}
diff --git a/core/modules/user/lib/Drupal/user/Controller/UserListController.php b/core/modules/user/lib/Drupal/user/Controller/UserListController.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f8da1d77b004ae8eb9892f6cb5593e9bc6a4653
--- /dev/null
+++ b/core/modules/user/lib/Drupal/user/Controller/UserListController.php
@@ -0,0 +1,166 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\user\Controller\UserListController.
+ */
+
+namespace Drupal\user\Controller;
+
+use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityListController;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Lists user entities.
+ *
+ * @see \Drupal\user\Entity\User
+ */
+class UserListController extends EntityListController implements EntityControllerInterface {
+
+  /**
+   * The entity query factory.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
+   * Constructs a new UserListController object.
+   *
+   * @param string $entity_type
+   *   The type of entity to be listed.
+   * @param array $entity_info
+   *   An array of entity info for the entity type.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage
+   *   The entity storage controller class.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler to invoke hooks on.
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query factory.
+   */
+  public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, QueryFactory $query_factory) {
+    parent::__construct($entity_type, $entity_info, $storage, $module_handler);
+    $this->queryFactory = $query_factory;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+    return new static(
+      $entity_type,
+      $entity_info,
+      $container->get('entity.manager')->getStorageController($entity_type),
+      $container->get('module_handler'),
+      $container->get('entity.query')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function load() {
+    $entity_query = $this->queryFactory->get('user');
+    $entity_query->condition('uid', 0, '<>');
+    $entity_query->pager(50);
+    $header = $this->buildHeader();
+    $entity_query->tableSort($header);
+    $uids = $entity_query->execute();
+    return $this->storage->loadMultiple($uids);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildHeader() {
+    $header = array(
+      'username' => array(
+        'data' => $this->t('Username'),
+        'field' => 'name',
+        'specifier' => 'name',
+      ),
+      'status' => array(
+        'data' => $this->t('Status'),
+        'field' => 'status',
+        'specifier' => 'status',
+        'class' => array(RESPONSIVE_PRIORITY_LOW),
+      ),
+      'roles' => array(
+        'data' => $this->t('Roles'),
+        'class' => array(RESPONSIVE_PRIORITY_LOW),
+      ),
+      'member_for' => array(
+        'data' => $this->t('Member for'),
+        'field' => 'created',
+        'specifier' => 'created',
+        'sort' => 'desc',
+        'class' => array(RESPONSIVE_PRIORITY_LOW),
+      ),
+      'access' => array(
+        'data' => $this->t('Last access'),
+        'field' => 'access',
+        'specifier' => 'access',
+        'class' => array(RESPONSIVE_PRIORITY_LOW),
+      ),
+    );
+    return $header + parent::buildHeader();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row['username']['data'] = array(
+      '#theme' => 'username',
+      '#account' => $entity,
+    );
+    $row['status'] = $entity->isActive() ? $this->t('active') : $this->t('blocked');
+
+    $roles = array_map('\Drupal\Component\Utility\String::checkPlain', user_role_names(TRUE));
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);
+    $users_roles = array();
+    foreach ($entity->getRoles() as $role) {
+      if (isset($roles[$role])) {
+        $users_roles[] = $roles[$role];
+      }
+    }
+    asort($users_roles);
+    $row['roles']['data'] = array(
+      '#theme' => 'item_list',
+      '#items' => $users_roles,
+    );
+    $row['member_for'] = format_interval(REQUEST_TIME - $entity->getCreatedTime());
+    $row['access'] = $entity->access ? $this->t('@time ago', array(
+      '@time' => format_interval(REQUEST_TIME - $entity->getLastAccessedTime()),
+    )) : t('never');
+    return $row + parent::buildRow($entity);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getOperations(EntityInterface $entity) {
+    $operations = parent::getOperations($entity);
+    if (isset($operations['edit'])) {
+      $destination = drupal_get_destination();
+      $operations['edit']['query'] = $destination;
+    }
+    return $operations;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function render() {
+    $build['accounts'] = parent::render();
+    $build['accounts']['#empty'] = $this->t('No people available.');
+    $build['pager']['#theme'] = 'pager';
+    return $build;
+  }
+
+}
diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php
index c667d207cc0ae453bc9a7ecaed281ce7b6391da7..3d1815d4371dce0804c3225f1d31ee57519851c7 100644
--- a/core/modules/user/lib/Drupal/user/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Entity/User.php
@@ -21,6 +21,7 @@
  *   controllers = {
  *     "storage" = "Drupal\user\UserStorageController",
  *     "access" = "Drupal\user\UserAccessController",
+ *     "list" = "Drupal\user\Controller\UserListController",
  *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
  *     "form" = {
  *       "default" = "Drupal\user\ProfileFormController",
diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml
index eeb8d3d671558822dee36f9b3f5d169ff8a062d1..0a693e3afe676702fad0b44ef6f6a03153d2a6bf 100644
--- a/core/modules/user/user.routing.yml
+++ b/core/modules/user/user.routing.yml
@@ -44,7 +44,7 @@ user.account_settings:
 user.admin_account:
   path: '/admin/people'
   defaults:
-    _controller: '\Drupal\user\Controller\UserAdmin::userList'
+    _entity_list: 'user'
   requirements:
     _permission: 'administer users'