ListUtil.java
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.doris.common.util;
import org.apache.doris.catalog.ListPartitionItem;
import org.apache.doris.catalog.PartitionItem;
import org.apache.doris.catalog.PartitionKey;
import org.apache.doris.common.DdlException;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
public class ListUtil {
public static final Comparator<Map.Entry<Long, PartitionItem>> LIST_MAP_ENTRY_COMPARATOR =
Comparator.comparing(o -> ((ListPartitionItem) o.getValue()).getItems().iterator().next());
public static final Comparator<PartitionItem> PARTITION_KEY_COMPARATOR =
Comparator.comparing(o -> ((ListPartitionItem) o).getItems().iterator().next());
/**
* split a list to multi expected number sublist
* for example:
*
* list is : [1, 2, 3, 4, 5, 6, 7]
* expectedSize is : 3
*
* return :
* [1, 4, 7]
* [2, 5]
* [3, 6]
*/
public static <T> List<List<T>> splitBySize(List<T> list, int expectedSize)
throws NullPointerException, IllegalArgumentException {
Preconditions.checkNotNull(list, "list must not be null");
Preconditions.checkArgument(expectedSize > 0, "expectedSize must larger than 0");
int splitSize = Math.min(expectedSize, list.size());
List<List<T>> result = new ArrayList<List<T>>(splitSize);
for (int i = 0; i < splitSize; i++) {
result.add(new ArrayList<>());
}
int index = 0;
for (T t : list) {
result.get(index).add(t);
index = (index + 1) % splitSize;
}
return result;
}
public static void checkPartitionKeyListsMatch(List<PartitionItem> list1,
List<PartitionItem> list2) throws DdlException {
list1.sort(PARTITION_KEY_COMPARATOR);
list2.sort(PARTITION_KEY_COMPARATOR);
int idx1 = 0;
int idx2 = 0;
List<PartitionKey> keys1 = new ArrayList<>(list1.get(idx1).getItems());
List<PartitionKey> keys2 = new ArrayList<>(list2.get(idx2).getItems());
while (true) {
int size = Math.min(keys1.size(), keys2.size());
for (int i = 0; i < size; i++) {
int res = keys1.get(i).compareTo(keys2.get(i));
if (res != 0) {
throw new DdlException("2 partition key lists are not matched. "
+ keys1 + " vs. " + keys2);
}
}
int res = keys1.size() - keys2.size();
if (res == 0) {
++idx1;
++idx2;
if (idx1 == list1.size() || idx2 == list2.size()) {
break;
}
keys1.clear();
keys2.clear();
keys1.addAll(list1.get(idx1).getItems());
keys2.addAll(list2.get(idx2).getItems());
} else if (res > 0) {
if (++idx2 == list2.size()) {
break;
}
keys1.removeAll(keys2);
keys2.clear();
keys2.addAll(list2.get(idx2).getItems());
} else {
if (++idx1 == list1.size()) {
break;
}
keys2.removeAll(keys1);
keys1.clear();
keys1.addAll(list1.get(idx1).getItems());
}
}
if (idx1 < list1.size() || idx2 < list2.size()) {
throw new DdlException("2 partition key lists are not matched. "
+ list1 + " vs. " + list2);
}
}
// Check if items in list2 conflicts with items in list1
public static void checkListsConflict(List<PartitionItem> list1, List<PartitionItem> list2) throws DdlException {
for (PartitionItem checkItem : list2) {
List<PartitionKey> checkKeys = checkItem.getItems();
for (PartitionKey checkKey : checkKeys) {
for (PartitionItem currentItem : list1) {
if (((ListPartitionItem) currentItem).getItems().contains(checkKey)) {
throw new DdlException("The partition key[" + checkKey.toSql()
+ "] is overlap with current " + currentItem);
}
}
}
}
}
}