以下のような配列を考えると、この配列を一意の値のみを持つ配列に変換する簡単な方法があるかどうか疑問に思いました。
これは与えられます:
numbers={5,5,4,3,1,4,5,4,5}
元の順序を維持しながら、次のような結果配列に変換します。
{5,1,2,3,4}
Java 8ではIntStream
、配列の一意の要素を取得するために使用します
int[] noDuplicates = IntStream.of(array).distinct().toArray();
最も簡単な方法は、配列からセットを作成することです。
Integer[] array = ...
Set<Integer> set = new LinkedHashSet<Integer>(Arrays.asList(array ));
次に、次を使用して配列を取得できます。
set.toArray()
順序を維持する場合はLinkedHashSetを使用し、並べ替える場合はTreeSetを使用します。
2つのオプション
カウントと要素のマップを保持し、最後にカウント1の要素のみを使用します(追加のストレージが必要ですが、より高速です)
配列を並べ替え、配列内を移動するときは、繰り返されない配列のみを使用してください。
余分なスペースは必要ありませんが、O(n lg(n))になります
オブジェクトの配列を想定します。
Object[] arr;
{...omissis...}
List<Object> list = new ArrayList<Object>();
for(Object val: arr) {
if(!list.contains(val)) {
list.add(val);
}
}
list.toArray(new Object[0]);
Object
必要に応じて、配列クラスに置き換えます。
ここに2つのアイデアがあります:
すべてのアイテムをセットに追加するか、パラメーターとして配列を持つコンストラクターを使用してアイテムを作成します(HashSet
またはTreeSet
、必要な時間計算量に応じて)。次に、セット内の各要素について、それを削除し、セットのサイズである新しい配列の次の開いた位置に追加します。
配列を並べ替えます。インデックス0のオブジェクトをに追加しますArrayList
。インデックス1から開始し、インデックスに移動しますlength - 1
。現在の要素が前のインデックスの要素と等しくないArrayList
場合は、それをに追加します。ArrayList
必要に応じて、を配列に変更します。
(再投稿: https://stackoverflow.com/a/39731584/1520422 )
Java8のStreamAPIを使用すると、これは一般的な配列型のソリューションです。
public static <T> T[] makeUnique(T... values)
{
return Arrays.stream(values).distinct().toArray(new IntFunction<T[]>()
{
@Override
public T[] apply(int length)
{
return (T[]) Array.newInstance(values.getClass().getComponentType(), length);
}
});
}
これは、任意のオブジェクト型配列に対して機能しますが、プリミティブ配列に対しては機能しません。
プリミティブ配列の場合、次のようになります。
public static int[] makeUnique(int... values)
{
return Arrays.stream(values).distinct().toArray();
}
そして最後に、ここに小さな単体テストがあります。
@Test
public void testMakeUnique()
{
assertArrayEquals(new String[] { "a", "b", "c" }, makeUnique("a", "b", "c", "b", "a"));
assertArrayEquals(new Object[] { "a", "b", "c" }, makeUnique(new Object[] { "a", "b", "c", "b", "a" }));
assertArrayEquals(new Integer[] { 1, 2, 3, 4, 5 }, makeUnique(new Integer[] { 1, 2, 2, 3, 3, 3, 1, 4, 5, 5, 5, 1 }));
assertArrayEquals(new int[] { 1, 2, 3, 4, 5 }, makeUnique(new int[] { 1, 2, 2, 3, 3, 3, 1, 4, 5, 5, 5, 1 }));
}
重複せずに2つのリストをマージしたい場合は、これを試してください。
List<Name> list1 = Arrays.asList(new Name("abc", 1), new Name("def", 2), new Name("ghi", 3));
List<Name> list2 = Arrays.asList(new Name("def", 4), new Name("jkl", 5), new Name("mno", 6));
List<Name> newNameList= new ArrayList<>(Stream.of(list1, list2).flatMap(List::stream)
.collect(Collectors.toMap(Name::getName, d -> d, (Name x, Name y) -> x == null ? y : x)).values());
newNameList.forEach(System.out::println);
class Name {
String name;
int id;
public Name(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Name{" + "name='" + name + '\'' + ", id=" + id + '}';
}
}