### Description

`TransportFieldCapabilitiesAction` (used for the the `_field_caps` endpoint) has got a nested loop in `merge` method when unmapped fields are included (https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java#L245). This loops over indices -> fields -> indices, which could cause an exponential blowup in objects used when there's a large number of indices and unmapped fields.

We could be more efficient in creating & sharing IndexCap objects in these situations.
server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java
indices = indiceList.stream().map(caps -> caps.name).toArray(String[]::new);
            } else {
                indices = null;
            }
            
            
            final boolean isSearchable = searchableIndices == indiceList.size();
            final String[] nonSearchableIndices;
            if (isSearchable || searchableIndices == 0) {
                nonSearchableIndices = null;
            } else {
                nonSearchableIndices = new String[indiceList.size() - searchableIndices];
                int index = 0;
                for (IndexCaps indexCaps : indiceList) {
                    if (indexCaps.isSearchable == false) {
                        nonSearchableIndices[index++] = indexCaps.name;
                    }
                }
            }
            
            
            final boolean isAggregatable = aggregatableIndices == indiceList.size();
            final String[] nonAggregatableIndices;
            if (isAggregatable || aggregatableIndices == 0) {
                nonAggregatableIndices = null;
            } else {
                nonAggregatableIndices = new String[indiceList.size() - aggregatableIndices];
                int index = 0;
                for (IndexCaps indexCaps : indiceList) {
                    if (indexCaps.isAggregatable == false) {