public static String queryParamString(final Collection<Map.Entry<String, String>> params) {
    final StringBuilder sb = new StringBuilder();
    if (params.isEmpty()) {
      return sb.toString();
    }
    sb.append("?");
    sb.append(params.stream()
        .map(e -> "%s=%s".formatted(
            URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8),
            URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8)))
        .collect(Collectors.joining("&")));
    return sb.toString();
  }
@Test
  public void queryParameterStringPreservesOrder() {
    final String result = HttpUtils.queryParamString(List.of(
        Map.entry("a", "aval"),
        Map.entry("b", "bval1"),
        Map.entry("b", "bval2")
    ));
    // https://url.spec.whatwg.org/#example-constructing-urlsearchparams allows multiple parameters with the same key
    // https://url.spec.whatwg.org/#example-searchparams-sort implies that the relative order of values for parameters
    // with the same key must be preserved
    assertThat(result).isEqualTo("?a=aval&b=bval1&b=bval2");
  }