Вы можете получить поток из List
и вставить в TreeSet
, из которого вы предоставили пользовательский компаратор, который однозначно сравнивает идентификатор.
Тогда, если вам действительно нужен список, вы можете поместить обратно эту коллекцию в ArrayList.
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;
...
List<Employee> unique = employee.stream()
.collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Employee::getId))),
ArrayList::new));
На примере:
List<Employee> employee = Arrays.asList(new Employee(1, "John"), new Employee(1, "Bob"), new Employee(2, "Alice"));
It будет выводиться:
[Employee{id=1, name='John'}, Employee{id=2, name='Alice'}]
Еще одна идея может заключаться в использовании обертки, которая обертывает сотрудника и имеет метод equals и hashcode, основанный на его id:
class WrapperEmployee {
private Employee e;
public WrapperEmployee(Employee e) {
this.e = e;
}
public Employee unwrap() {
return this.e;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WrapperEmployee that = (WrapperEmployee) o;
return Objects.equals(e.getId(), that.e.getId());
}
@Override
public int hashCode() {
return Objects.hash(e.getId());
}
}
Затем вы завершаете каждый экземпляр, вызываете distinct()
, разворачиваете их и собираете результат в списке.
List<Employee> unique = employee.stream()
.map(WrapperEmployee::new)
.distinct()
.map(WrapperEmployee::unwrap)
.collect(toList());
На самом деле, я думаю, вы можете сделать эту общую оболочку, предоставив функцию, которая выполнит сравнение:
class Wrapper<T, U> {
private T t;
private Function<T, U> equalityFunction;
public Wrapper(T t, Function<T, U> equalityFunction) {
this.t = t;
this.equalityFunction = equalityFunction;
}
public T unwrap() {
return this.t;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@SuppressWarnings("unchecked")
Wrapper<T, U> that = (Wrapper<T, U>) o;
return Objects.equals(equalityFunction.apply(this.t), that.equalityFunction.apply(that.t));
}
@Override
public int hashCode() {
return Objects.hash(equalityFunction.apply(this.t));
}
}
, а отображение будет:
.map(e -> new Wrapper<>(e, Employee::getId))
Вы можете использовать DropDownList
вместо EdiorFor
, например:
@Html.DropDownList("state" + Model.Index, new SelectList(Model.States, "", ""))
Также вы можете переопределить идентификатор при использовании DropDownListFor
:
@Html.DropDownListFor(m => m.state, new SelectList(Model.States, "", ""), new { id = "state" + Model.Index })
Это должно поставить вас на правильный путь:
@Html.LabelFor(model => model.YourItem, "State: ", new { @id = "MyID"})
@Html.EditorFor(model => model.YourItem, new { @id = "MyID2"})
И это позволит вам стилизовать метку / редактор с помощью CSS, как обычно. Надеюсь, это поможет!
<div class="editor-field">
@Html.EditorFor(p => p.item.property, new { htmlAttributes = new { @id="itemId" }})
</div>
Для всех методов Asp.Net MVC вы можете установить объект viewData, который устанавливает дополнительные значения atrtibute в сгенерированный HTML:
@Html.EditorFor(
modelItem => item.YourProperty,
new { htmlAttributes = new { @id="custom_id" } })
для получения дополнительной информации. this .